// Copyright (c) 2016, 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.

library kernel.ast_from_binary;

import 'dart:developer';
import 'dart:convert';
import 'dart:typed_data';

import '../ast.dart';
import '../transformations/flags.dart';
import 'tag.dart';

const int $_ = 95;

class ParseError {
  final String? filename;
  final int byteIndex;
  final String message;
  final String path;

  ParseError(this.message,
      {required this.filename, required this.byteIndex, required this.path});

  @override
  String toString() => '$filename:$byteIndex: $message at $path';
}

class InvalidKernelVersionError {
  final String? filename;
  final int version;

  InvalidKernelVersionError(this.filename, this.version);

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write('Unexpected Kernel Format Version ${version} '
        '(expected ${Tag.BinaryFormatVersion})');
    if (filename != null) {
      sb.write(' when reading $filename.');
    }
    return '$sb';
  }
}

class InvalidKernelSdkVersionError {
  final String version;

  InvalidKernelSdkVersionError(this.version);

  @override
  String toString() {
    return 'Unexpected Kernel SDK Version ${version} '
        '(expected ${expectedSdkHash}).';
  }
}

class CompilationModeError {
  final String message;

  CompilationModeError(this.message);

  @override
  String toString() => "CompilationModeError[$message]";
}

class _ComponentIndex {
  static const int numberOfFixedFields = 12;

  final int binaryOffsetForSourceTable;
  final int binaryOffsetForCanonicalNames;
  final int binaryOffsetForMetadataPayloads;
  final int binaryOffsetForMetadataMappings;
  final int binaryOffsetForStringTable;
  final int binaryOffsetForConstantTable;
  final int binaryOffsetForConstantTableIndex;
  final int binaryOffsetForStartOfComponentIndex;
  final int mainMethodReference;
  final List<int> libraryOffsets;
  final int libraryCount;
  final int componentFileSizeInBytes;

  _ComponentIndex(
      {required this.binaryOffsetForSourceTable,
      required this.binaryOffsetForCanonicalNames,
      required this.binaryOffsetForMetadataPayloads,
      required this.binaryOffsetForMetadataMappings,
      required this.binaryOffsetForStringTable,
      required this.binaryOffsetForConstantTable,
      required this.binaryOffsetForConstantTableIndex,
      required this.binaryOffsetForStartOfComponentIndex,
      required this.mainMethodReference,
      required this.libraryOffsets,
      required this.libraryCount,
      required this.componentFileSizeInBytes});
}

class SubComponentView {
  final List<Library> libraries;
  final int componentStartOffset;
  final int componentFileSize;

  SubComponentView(
      this.libraries, this.componentStartOffset, this.componentFileSize);
}

/// [StringInterner] allows Strings created from the binary to be shared with
/// other components.
///
/// The [StringInterner] is an optional parameter to [BinaryBuilder], so sharing
/// should not be required for correctness, and an implementation of
/// [StringInterner] method may be partial (sometimes not finding an existing
/// object) or trivial (returning the argument).
abstract class StringInterner {
  /// Returns a string with the same contents as [string].
  String internString(String string);
}

/// Helper used to trigger the read of a late variable in asserts.
bool _lateIsInitialized(dynamic value) {
  return true;
}

class BinaryBuilder {
  final List<VariableDeclaration> variableStack = <VariableDeclaration>[];
  final List<LabeledStatement> labelStack = <LabeledStatement>[];
  int labelStackBase = 0;
  int switchCaseStackBase = 0;
  final List<SwitchCase> switchCaseStack = <SwitchCase>[];
  final List< /* TypeParameter | StructuralParameter */ Object>
      typeParameterStack = <Object>[];
  final String? filename;
  final Uint8List _bytes;
  int _byteOffset = 0;
  List<String> _stringTable = const [];
  late Map<int, Name?> _nameCache;
  List<Uri> _sourceUriTable = const [];
  List<Constant> _constantTable = const <Constant>[];
  late List<CanonicalName> _linkTable;

  /// Advanced use only. Coordinate with the kernel team.
  List<CanonicalName> get linkTable => _linkTable;

  late Map<int, DartType?> _cachedSimpleInterfaceTypes;
  List<FunctionType?> _voidFunctionFunctionTypesCache = [
    null,
    null,
    null,
    null
  ];
  int _transformerFlags = 0;
  Library? _currentLibrary;
  int _componentStartOffset = 0;

  // If something goes wrong, this list should indicate what library,
  // class, and member was being built.
  List<String> debugPath = <String>[];

  final bool alwaysCreateNewNamedNodes;

  /// If binary contains metadata section with payloads referencing other nodes
  /// such Kernel binary can't be read lazily because metadata cross references
  /// will not be resolved correctly.
  bool _disableLazyReading = false;

  /// If binary contains metadata section with payloads referencing other nodes
  /// such Kernel binary can't be read lazily because metadata cross references
  /// will not be resolved correctly.
  bool _disableLazyClassReading = false;

  /// [stringInterner] (optional) may be used to allow components to share
  /// instances of [String] that have the same contents.
  final StringInterner? stringInterner;

  /// When creating lists that *might* be growable, use this boolean as the
  /// setting to pass to `growable` so the dill can be loaded in a more compact
  /// manner if the caller knows that the growability isn't needed.
  final bool useGrowableLists;

  /// Note that [disableLazyClassReading] is incompatible
  /// with checkCanonicalNames on readComponent.
  BinaryBuilder(this._bytes,
      {this.filename,
      bool disableLazyReading = false,
      bool disableLazyClassReading = false,
      bool? alwaysCreateNewNamedNodes,
      this.stringInterner,
      this.useGrowableLists = true})
      : _disableLazyReading = disableLazyReading,
        _disableLazyClassReading = disableLazyReading ||
            disableLazyClassReading ||
            // Disable lazy class reading when forcing the creation of new named
            // nodes as it is a logical "relink" to the new version (overwriting
            // the old one) - which doesn't play well with lazy loading class
            // content as old loaded references will then potentially still
            // point to the old content until the new class has been lazy
            // loaded.
            (alwaysCreateNewNamedNodes == true),
        this.alwaysCreateNewNamedNodes = alwaysCreateNewNamedNodes ?? false;

  Never fail(String message) {
    throw ParseError(message,
        byteIndex: _byteOffset, filename: filename, path: debugPath.join('::'));
  }

  int get byteOffset => _byteOffset;

  int readByte() => _bytes[_byteOffset++];
  int peekByte() => _bytes[_byteOffset];

  int readUInt30() {
    int byte = readByte();
    if (byte & 0x80 == 0) {
      // 0xxxxxxx
      return byte;
    } else if (byte & 0x40 == 0) {
      // 10xxxxxx
      return ((byte & 0x3F) << 8) | readByte();
    } else {
      // 11xxxxxx
      return ((byte & 0x3F) << 24) |
          (readByte() << 16) |
          (readByte() << 8) |
          readByte();
    }
  }

  int readUint32() {
    return (readByte() << 24) |
        (readByte() << 16) |
        (readByte() << 8) |
        readByte();
  }

  final Float64List _doubleBuffer = new Float64List(1);
  Uint8List? _doubleBufferUint8;

  double readDouble() {
    Uint8List doubleBufferUint8 =
        _doubleBufferUint8 ??= _doubleBuffer.buffer.asUint8List();
    doubleBufferUint8[0] = readByte();
    doubleBufferUint8[1] = readByte();
    doubleBufferUint8[2] = readByte();
    doubleBufferUint8[3] = readByte();
    doubleBufferUint8[4] = readByte();
    doubleBufferUint8[5] = readByte();
    doubleBufferUint8[6] = readByte();
    doubleBufferUint8[7] = readByte();
    return _doubleBuffer[0];
  }

  Uint8List readBytes(int length) {
    Uint8List bytes = new Uint8List(length);
    bytes.setRange(0, bytes.length, _bytes, _byteOffset);
    _byteOffset += bytes.length;
    return bytes;
  }

  Uint8List readByteList() {
    return readBytes(readUInt30());
  }

  Uint8List readOrViewByteList() {
    int length = readUInt30();
    List<int> source = _bytes;
    if (source is Uint8List) {
      Uint8List view =
          source.buffer.asUint8List(source.offsetInBytes + _byteOffset, length);
      _byteOffset += length;
      return view;
    }
    return readBytes(length);
  }

  String readString() {
    return readStringEntry(readUInt30());
  }

  String readStringEntry(int numBytes) {
    String string = _readStringEntry(numBytes);
    if (stringInterner == null) return string;
    return stringInterner!.internString(string);
  }

  String _readStringEntry(int numBytes) {
    int start = _byteOffset;
    int end = start + numBytes;
    _byteOffset = end;
    for (int i = start; i < end; i++) {
      if (_bytes[i] > 127) {
        return _decodeWtf8(start, end);
      }
    }
    return new String.fromCharCodes(_bytes, start, end);
  }

  String _decodeWtf8(int start, int end) {
    // WTF-8 decoder that trusts its input, meaning that the correctness of
    // the code depends on the bytes from start to end being valid and
    // complete WTF-8. Instead of masking off the control bits from every
    // byte, it simply xor's the byte values together at their appropriate
    // bit shifts, and then xor's out all of the control bits at once.
    Uint16List charCodes = new Uint16List(end - start);
    int i = start;
    int j = 0;
    while (i < end) {
      int byte = _bytes[i++];
      if (byte < 0x80) {
        // ASCII.
        charCodes[j++] = byte;
      } else if (byte < 0xE0) {
        // Two-byte sequence (11-bit unicode value).
        int byte2 = _bytes[i++];
        int value = (byte << 6) ^ byte2 ^ 0x3080;
        assert(value >= 0x80 && value < 0x800);
        charCodes[j++] = value;
      } else if (byte < 0xF0) {
        // Three-byte sequence (16-bit unicode value).
        int byte2 = _bytes[i++];
        int byte3 = _bytes[i++];
        int value = (byte << 12) ^ (byte2 << 6) ^ byte3 ^ 0xE2080;
        assert(value >= 0x800 && value < 0x10000);
        charCodes[j++] = value;
      } else {
        // Four-byte sequence (non-BMP unicode value).
        int byte2 = _bytes[i++];
        int byte3 = _bytes[i++];
        int byte4 = _bytes[i++];
        int value =
            (byte << 18) ^ (byte2 << 12) ^ (byte3 << 6) ^ byte4 ^ 0x3C82080;
        assert(value >= 0x10000 && value < 0x110000);
        charCodes[j++] = 0xD7C0 + (value >> 10);
        charCodes[j++] = 0xDC00 + (value & 0x3FF);
      }
    }
    assert(i == end);
    return new String.fromCharCodes(charCodes, 0, j);
  }

  /// Read metadataMappings section from the binary.
  void _readMetadataMappings(
      Component component, int binaryOffsetForMetadataPayloads) {
    // Default reader ignores metadata section entirely.
  }

  /// Reads metadata for the given [node].
  T _associateMetadata<T extends Node>(T node, int nodeOffset) {
    // Default reader ignores metadata section entirely.
    return node;
  }

  void readStringTable() {
    // Read the table of end offsets.
    int length = readUInt30();
    List<int> endOffsets =
        new List<int>.generate(length, (_) => readUInt30(), growable: false);
    // Read the WTF-8 encoded strings.
    int startOffset = 0;

    // Reset name cache here to make any index into it always
    // be about the corresponding string table entry.
    _nameCache = {};
    _stringTable = new List<String>.generate(length, (int index) {
      String result = readStringEntry(endOffsets[index] - startOffset);
      startOffset = endOffsets[index];
      return result;
    }, growable: false);
  }

  void readConstantTable() {
    final int length = readUInt30();
    // Because of "back-references" (e.g. the 10th constant referencing the 3rd
    // constant) we can't use List.generate.
    _constantTable =
        new List<Constant>.filled(length, dummyConstant, growable: false);
    for (int i = 0; i < length; i++) {
      _constantTable[i] = readConstantTableEntry();
    }
  }

  Constant readConstantTableEntry() {
    final int constantTag = readByte();
    switch (constantTag) {
      case ConstantTag.NullConstant:
        return _readNullConstant();
      case ConstantTag.BoolConstant:
        return _readBoolConstant();
      case ConstantTag.IntConstant:
        return _readIntConstant();
      case ConstantTag.DoubleConstant:
        return _readDoubleConstant();
      case ConstantTag.StringConstant:
        return _readStringConstant();
      case ConstantTag.SymbolConstant:
        return _readSymbolConstant();
      case ConstantTag.MapConstant:
        return _readMapConstant();
      case ConstantTag.ListConstant:
        return _readListConstant();
      case ConstantTag.SetConstant:
        return _readSetConstant();
      case ConstantTag.RecordConstant:
        return _readRecordConstant();
      case ConstantTag.InstanceConstant:
        return _readInstanceConstant();
      case ConstantTag.InstantiationConstant:
        return _readInstantiationConstant();
      case ConstantTag.TypedefTearOffConstant:
        return _readTypedefTearOffConstant();
      case ConstantTag.StaticTearOffConstant:
        return _readStaticTearOffConstant();
      case ConstantTag.ConstructorTearOffConstant:
        return _readConstructorTearOffConstant();
      case ConstantTag.RedirectingFactoryTearOffConstant:
        return _readRedirectingFactoryTearOffConstant();
      case ConstantTag.TypeLiteralConstant:
        return _readTypeLiteralConstant();
      case ConstantTag.UnevaluatedConstant:
        return _readUnevaluatedConstant();
    }

    throw fail('unexpected constant tag: $constantTag');
  }

  Constant _readNullConstant() {
    return new NullConstant();
  }

  Constant _readBoolConstant() {
    return new BoolConstant(readByte() == 1);
  }

  Constant _readIntConstant() {
    return new IntConstant((readExpression() as IntLiteral).value);
  }

  Constant _readDoubleConstant() {
    return new DoubleConstant(readDouble());
  }

  Constant _readStringConstant() {
    return new StringConstant(readStringReference());
  }

  Constant _readSymbolConstant() {
    Reference? libraryReference = readNullableLibraryReference();
    return new SymbolConstant(readStringReference(), libraryReference);
  }

  Constant _readMapConstant() {
    final DartType keyType = readDartType();
    final DartType valueType = readDartType();
    final int length = readUInt30();
    final List<ConstantMapEntry> entries =
        new List<ConstantMapEntry>.generate(length, (_) {
      final Constant key = readConstantReference();
      final Constant value = readConstantReference();
      return new ConstantMapEntry(key, value);
    }, growable: useGrowableLists);
    return new MapConstant(keyType, valueType, entries);
  }

  Constant _readListConstant() {
    final DartType typeArgument = readDartType();
    List<Constant> entries = _readConstantReferenceList();
    return new ListConstant(typeArgument, entries);
  }

  Constant _readSetConstant() {
    final DartType typeArgument = readDartType();
    List<Constant> entries = _readConstantReferenceList();
    return new SetConstant(typeArgument, entries);
  }

  Constant _readRecordConstant() {
    List<Constant> positional = _readConstantReferenceList();
    final int namedLength = readUInt30();
    final List<MapEntry<String, Constant>> named =
        new List<MapEntry<String, Constant>>.generate(namedLength, (_) {
      final String name = readStringReference();
      final Constant value = readConstantReference();
      return new MapEntry<String, Constant>(name, value);
    }, growable: useGrowableLists);
    final RecordType recordType = readDartType() as RecordType;
    return new RecordConstant(
        positional, new Map<String, Constant>.fromEntries(named), recordType);
  }

  Constant _readInstanceConstant() {
    final Reference classReference = readNonNullClassReference();
    final List<DartType> typeArguments = readDartTypeList();
    final int fieldValueCount = readUInt30();
    final Map<Reference, Constant> fieldValues = <Reference, Constant>{};
    for (int i = 0; i < fieldValueCount; i++) {
      final Reference fieldRef = readNonNullCanonicalNameReference().reference;
      final Constant constant = readConstantReference();
      fieldValues[fieldRef] = constant;
    }
    return new InstanceConstant(classReference, typeArguments, fieldValues);
  }

  Constant _readInstantiationConstant() {
    final Constant tearOffConstant = readConstantReference();
    final List<DartType> types = readDartTypeList();
    return new InstantiationConstant(tearOffConstant, types);
  }

  Constant _readTypedefTearOffConstant() {
    final List<StructuralParameter> parameters =
        readAndPushStructuralParameterList();
    final TearOffConstant tearOffConstant =
        readConstantReference() as TearOffConstant;
    final List<DartType> types = readDartTypeList();
    typeParameterStack.length -= parameters.length;
    return new TypedefTearOffConstant(parameters, tearOffConstant, types);
  }

  Constant _readStaticTearOffConstant() {
    final Reference reference = readNonNullCanonicalNameReference().reference;
    return new StaticTearOffConstant.byReference(reference);
  }

  Constant _readConstructorTearOffConstant() {
    final Reference reference = readNonNullCanonicalNameReference().reference;
    return new ConstructorTearOffConstant.byReference(reference);
  }

  Constant _readRedirectingFactoryTearOffConstant() {
    final Reference reference = readNonNullCanonicalNameReference().reference;
    return new RedirectingFactoryTearOffConstant.byReference(reference);
  }

  Constant _readTypeLiteralConstant() {
    final DartType type = readDartType();
    return new TypeLiteralConstant(type);
  }

  Constant _readUnevaluatedConstant() {
    final Expression expression = readExpression();
    return new UnevaluatedConstant(expression);
  }

  Constant readConstantReference() {
    final int index = readUInt30();
    Constant constant = _constantTable[index];
    assert(!identical(constant, dummyConstant),
        "No constant found at index $index.");
    return constant;
  }

  List<Constant> _readConstantReferenceList() {
    final int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfConstant;
    }
    return new List<Constant>.generate(length, (_) => readConstantReference(),
        growable: useGrowableLists);
  }

  Uri readUriReference() {
    return _sourceUriTable[readUInt30()];
  }

  String readStringReference() {
    return _stringTable[readUInt30()];
  }

  List<String> readStringReferenceList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfString;
    }
    return new List<String>.generate(length, (_) => readStringReference(),
        growable: useGrowableLists);
  }

  String? readStringOrNullIfEmpty() {
    String string = readStringReference();
    return string.isEmpty ? null : string;
  }

  bool readAndCheckOptionTag() {
    int tag = readByte();
    if (tag == Tag.Nothing) {
      return false;
    } else if (tag == Tag.Something) {
      return true;
    } else {
      throw fail('unexpected option tag: $tag');
    }
  }

  List<Expression> readAnnotationList([TreeNode? parent]) {
    int length = readUInt30();
    if (length == 0) return const <Expression>[];
    return new List<Expression>.generate(
        length, (_) => readExpression()..parent = parent,
        growable: useGrowableLists);
  }

  void readLinkTable(CanonicalName linkRoot) {
    int length = readUInt30();
    _linkTable = new List<CanonicalName>.filled(
        length,
        // Use [linkRoot] as a dummy default value.
        linkRoot,
        growable: false);
    // Reset simple interface type cache here to make any index into it always
    // be about the corresponding link table entry.
    _cachedSimpleInterfaceTypes = {};
    for (int i = 0; i < length; ++i) {
      int biasedParentIndex = readUInt30();
      String name = readStringReference();
      CanonicalName parent =
          biasedParentIndex == 0 ? linkRoot : _linkTable[biasedParentIndex - 1];
      _linkTable[i] = parent.getChild(name);
    }
  }

  List<int> _indexComponents() {
    _checkEmptyInput();
    int savedByteOffset = _byteOffset;
    _byteOffset = _bytes.length - 4;
    List<int> index = <int>[];
    while (_byteOffset > 0) {
      int size = readUint32();
      if (size <= 0) {
        throw fail("invalid size '$size' reported at offset $byteOffset");
      }
      int start = _byteOffset - size;
      if (start < 0) {
        throw fail("indicated size does not match file size");
      }
      index.add(size);
      _byteOffset = start - 4;
    }
    _byteOffset = savedByteOffset;
    return new List.of(index.reversed);
  }

  void _checkEmptyInput() {
    if (_bytes.length == 0) throw new StateError("Empty input given.");
  }

  void _readAndVerifySdkHash() {
    final String sdkHash = ascii.decode(readBytes(sdkHashLength));
    if (!isValidSdkHash(sdkHash)) {
      throw InvalidKernelSdkVersionError(sdkHash);
    }
  }

  /// Splits the input into views of the sub-components.
  ///
  /// Note that the result will not have the libraries filled out.
  static List<SubComponentView> index(Uint8List bytes) {
    BinaryBuilder bb = new BinaryBuilder(bytes);
    bb._verifyComponentInitialBytes(resetOffset: true);
    List<int> componentFileSizes = bb._indexComponents();
    int componentFileIndex = 0;
    List<SubComponentView> views = [];
    while (bb._byteOffset < bb._bytes.length) {
      int componentStartOffset = bb._byteOffset;
      int componentFileSize = componentFileSizes[componentFileIndex];
      bb._verifyComponentInitialBytes(resetOffset: true);
      views.add(new SubComponentView(
          const [], componentStartOffset, componentFileSize));

      bb._byteOffset = componentStartOffset + componentFileSize;
      ++componentFileIndex;
    }
    return views;
  }

  /// Deserializes a kernel component and stores it in [component].
  ///
  /// When linking with a non-empty component, canonical names must have been
  /// computed ahead of time.
  ///
  /// The input bytes may contain multiple files concatenated.
  ///
  /// If [createView] is true, returns a list of [SubComponentView] - one for
  /// each concatenated dill - each of which knowing where in the combined dill
  /// it came from. If [createView] is false null will be returned.
  List<SubComponentView>? readComponent(Component component,
      {bool checkCanonicalNames = false, bool createView = false}) {
    return Timeline.timeSync<List<SubComponentView>?>(
        "BinaryBuilder.readComponent", () {
      _verifyComponentInitialBytes(resetOffset: true);

      List<int> componentFileSizes = _indexComponents();
      if (componentFileSizes.length > 1) {
        _disableLazyReading = true;
        _disableLazyClassReading = true;
      }
      int componentFileIndex = 0;
      List<SubComponentView>? views;
      if (createView) {
        views = <SubComponentView>[];
      }
      while (_byteOffset < _bytes.length) {
        SubComponentView? view = _readOneComponent(
            component, componentFileSizes[componentFileIndex],
            createView: createView);
        if (createView) {
          views!.add(view!);
        }
        ++componentFileIndex;
      }

      if (checkCanonicalNames) {
        component.root.checkCanonicalNameChildren();
      }
      return views;
    });
  }

  /// Deserializes the source and stores it in [component].
  /// Note that the _coverage_ normally included in the source in the
  /// uri-to-source mapping is _not_ included.
  ///
  /// The input bytes may contain multiple files concatenated.
  void readComponentSource(Component component) {
    List<int> componentFileSizes = _indexComponents();
    if (componentFileSizes.length > 1) {
      _disableLazyReading = true;
      _disableLazyClassReading = true;
    }
    int componentFileIndex = 0;
    while (_byteOffset < _bytes.length) {
      _readOneComponentSource(
          component, componentFileSizes[componentFileIndex]);
      ++componentFileIndex;
    }
  }

  /// Reads a single component file from the input and loads it into
  /// [component], overwriting and reusing any existing data in the component.
  ///
  /// When linking with a non-empty component, canonical names must have been
  /// computed ahead of time.
  ///
  /// This should *only* be used when there is a reason to not allow
  /// concatenated files.
  void readSingleFileComponent(Component component,
      {bool checkCanonicalNames = false}) {
    List<int> componentFileSizes = _indexComponents();
    if (componentFileSizes.isEmpty) throw fail("invalid component data");
    _readOneComponent(component, componentFileSizes[0]);
    if (_byteOffset < _bytes.length) {
      if (_byteOffset + 3 < _bytes.length) {
        int magic = readUint32();
        if (magic == Tag.ComponentFile) {
          throw 'Concatenated component file given when a single component '
              'was expected.';
        }
      }
      throw 'Unrecognized bytes following component data';
    }

    if (checkCanonicalNames) {
      component.root.checkCanonicalNameChildren();
    }
  }

  _ComponentIndex _readComponentIndex(int componentFileSize) {
    int savedByteIndex = _byteOffset;

    // There are two fields: file size and library count.
    _byteOffset = _componentStartOffset + componentFileSize - (2) * 4;
    int libraryCount = readUint32();
    // Library offsets are used for start and end offsets, so there is one extra
    // element that this the end offset of the last library
    List<int> libraryOffsets = new List<int>.filled(
        libraryCount + 1,
        // Use `-1` as a dummy default value.
        -1,
        growable: false);
    int componentFileSizeInBytes = readUint32();
    if (componentFileSizeInBytes != componentFileSize) {
      throw "Malformed binary: This component file's component index indicates "
          "that the file size should be $componentFileSize but other component "
          "indexes has indicated that the size should be "
          "${componentFileSizeInBytes}.";
    }

    // Skip to the start of the index.
    _byteOffset -=
        ((libraryCount + 1) + _ComponentIndex.numberOfFixedFields) * 4;

    // Now read the component index.
    int binaryOffsetForSourceTable = _componentStartOffset + readUint32();
    int binaryOffsetForConstantTable = _componentStartOffset + readUint32();
    int binaryOffsetForConstantTableIndex =
        _componentStartOffset + readUint32();
    int binaryOffsetForCanonicalNames = _componentStartOffset + readUint32();
    int binaryOffsetForMetadataPayloads = _componentStartOffset + readUint32();
    int binaryOffsetForMetadataMappings = _componentStartOffset + readUint32();
    int binaryOffsetForStringTable = _componentStartOffset + readUint32();
    int binaryOffsetForStartOfComponentIndex =
        _componentStartOffset + readUint32();
    int mainMethodReference = readUint32();
    // TODO(jensj): Previously the component mode. Remove this.
    readUint32();
    for (int i = 0; i < libraryCount + 1; ++i) {
      libraryOffsets[i] = _componentStartOffset + readUint32();
    }

    _byteOffset = savedByteIndex;

    return new _ComponentIndex(
        libraryCount: libraryCount,
        libraryOffsets: libraryOffsets,
        componentFileSizeInBytes: componentFileSizeInBytes,
        binaryOffsetForSourceTable: binaryOffsetForSourceTable,
        binaryOffsetForCanonicalNames: binaryOffsetForCanonicalNames,
        binaryOffsetForMetadataPayloads: binaryOffsetForMetadataPayloads,
        binaryOffsetForMetadataMappings: binaryOffsetForMetadataMappings,
        binaryOffsetForStringTable: binaryOffsetForStringTable,
        binaryOffsetForConstantTable: binaryOffsetForConstantTable,
        binaryOffsetForConstantTableIndex: binaryOffsetForConstantTableIndex,
        binaryOffsetForStartOfComponentIndex:
            binaryOffsetForStartOfComponentIndex,
        mainMethodReference: mainMethodReference);
  }

  void _readOneComponentSource(Component component, int componentFileSize) {
    _componentStartOffset = _byteOffset;
    _verifyComponentInitialBytes(resetOffset: false);

    // Read component index from the end of this ComponentFiles serialized data.
    _ComponentIndex index = _readComponentIndex(componentFileSize);

    _byteOffset = index.binaryOffsetForSourceTable;
    Map<Uri, Source> uriToSource = readUriToSource(readCoverage: false);
    _mergeUriToSource(component.uriToSource, uriToSource);

    _byteOffset = _componentStartOffset + componentFileSize;
  }

  /// Verify the initial bytes could correspond to a valid component.
  ///
  /// * Checks we have non-empty input.
  /// * Verifies that the magic number is correct.
  /// * Verifies the binary format version.
  /// * Verifies the sdk hash.
  ///
  /// If [resetOffset] is true the [_byteOffset] will be reset to match what it
  /// was before this method was called. If false it will be so we read passed
  /// the sdk hash.
  void _verifyComponentInitialBytes({required bool resetOffset}) {
    // Check that we have a .dill file and it has the correct version before
    // we start decoding it.  Otherwise we will fail for cryptic reasons.
    _checkEmptyInput();
    int offset = _byteOffset;
    int magic = readUint32();
    if (magic != Tag.ComponentFile) {
      throw ArgumentError('Not a .dill file (wrong magic number).');
    }
    int version = readUint32();
    if (version != Tag.BinaryFormatVersion) {
      throw InvalidKernelVersionError(filename, version);
    }

    _readAndVerifySdkHash();

    if (resetOffset) {
      _byteOffset = offset;
    }
  }

  SubComponentView? _readOneComponent(
      Component component, int componentFileSize,
      {bool createView = false}) {
    _componentStartOffset = _byteOffset;
    _verifyComponentInitialBytes(resetOffset: false);

    List<String>? problemsAsJson = readListOfStrings();
    if (problemsAsJson != null) {
      component.problemsAsJson ??= <String>[];
      component.problemsAsJson!.addAll(problemsAsJson);
    }

    // Read component index from the end of this ComponentFiles serialized data.
    _ComponentIndex index = _readComponentIndex(componentFileSize);

    _byteOffset = index.binaryOffsetForStringTable;
    readStringTable();

    _byteOffset = index.binaryOffsetForCanonicalNames;
    readLinkTable(component.root);

    // TODO(alexmarkov): reverse metadata mappings and read forwards
    _byteOffset = index.binaryOffsetForStringTable; // Read backwards.
    _readMetadataMappings(component, index.binaryOffsetForMetadataPayloads);

    _associateMetadata(component, _componentStartOffset);

    _byteOffset = index.binaryOffsetForSourceTable;
    Map<Uri, Source> uriToSource = readUriToSource(readCoverage: true);
    _mergeUriToSource(component.uriToSource, uriToSource);

    _byteOffset = index.binaryOffsetForConstantTable;
    readConstantTable();
    // We don't need the constant table index on the dart side.

    int numberOfLibraries = index.libraryCount;

    SubComponentView? result;
    if (createView) {
      result = new SubComponentView(
          new List<Library>.generate(numberOfLibraries, (int i) {
            _byteOffset = index.libraryOffsets[i];
            return readLibrary(component, index.libraryOffsets[i + 1]);
          }, growable: false),
          _componentStartOffset,
          componentFileSize);
    } else {
      for (int i = 0; i < numberOfLibraries; ++i) {
        _byteOffset = index.libraryOffsets[i];
        readLibrary(component, index.libraryOffsets[i + 1]);
      }
    }

    Reference? mainMethod =
        getNullableMemberReferenceFromInt(index.mainMethodReference);
    component.setMainMethodAndMode(mainMethod, false);

    _byteOffset = _componentStartOffset + componentFileSize;

    assert(typeParameterStack.isEmpty);

    return result;
  }

  /// Read a list of strings. If the list is empty, [null] is returned.
  List<String>? readListOfStrings() {
    int length = readUInt30();
    if (length == 0) return null;
    return new List<String>.generate(length, (_) => readString(),
        growable: useGrowableLists);
  }

  /// Read the uri-to-source part of the binary.
  /// Note that this can include coverage, but that it is only included if
  /// [readCoverage] is true, otherwise coverage will be skipped. Note also that
  /// if [readCoverage] is true, references are read and that the link table
  /// thus has to be read first.
  Map<Uri, Source> readUriToSource({required bool readCoverage}) {
    assert(!readCoverage || (readCoverage && _lateIsInitialized(_linkTable)));

    int length = readUint32();

    // Read data.
    _sourceUriTable = new List<Uri>.filled(length, dummyUri, growable: false);
    Map<Uri, Source> uriToSource = <Uri, Source>{};
    for (int i = 0; i < length; ++i) {
      String uriString = readString();
      Uri uri = Uri.parse(uriString);
      _sourceUriTable[i] = uri;
      Uint8List sourceCode = readOrViewByteList();
      int lineCount = readUInt30();
      List<int> lineStarts = new List<int>.filled(
          lineCount,
          // Use `-1` as a dummy default value.
          -1,
          growable: false);
      int previousLineStart = 0;
      for (int j = 0; j < lineCount; ++j) {
        int lineStart = readUInt30() + previousLineStart;
        lineStarts[j] = lineStart;
        previousLineStart = lineStart;
      }
      String importUriString = readString();
      Uri importUri = Uri.parse(importUriString);

      Set<Reference>? coverageConstructors;
      {
        int constructorCoverageCount = readUInt30();
        if (constructorCoverageCount > 0) {
          if (readCoverage) {
            coverageConstructors = new Set<Reference>();
            for (int j = 0; j < constructorCoverageCount; ++j) {
              coverageConstructors.add(readNonNullMemberReference());
            }
          } else {
            for (int j = 0; j < constructorCoverageCount; ++j) {
              skipMemberReference();
            }
          }
        }
      }

      uriToSource[uri] = new Source(lineStarts, sourceCode, importUri, uri)
        ..constantCoverageConstructors = coverageConstructors;
    }

    // Read index.
    for (int i = 0; i < length; ++i) {
      readUint32();
    }
    return uriToSource;
  }

  // Add everything from [src] into [dst], but don't overwrite a non-empty
  // source with an empty source. Empty sources may be introduced by
  // synthetic, copy-down implementations such as mixin applications or
  // noSuchMethod forwarders.
  void _mergeUriToSource(Map<Uri, Source> dst, Map<Uri, Source> src) {
    if (dst.isEmpty) {
      // Fast path for the common case of one component per binary.
      dst.addAll(src);
    } else {
      src.forEach((Uri key, Source value) {
        Source? originalDestinationSource = dst[key];
        Source? mergeFrom;
        Source mergeTo;
        if (value.source.isNotEmpty || originalDestinationSource == null) {
          dst[key] = value;
          mergeFrom = originalDestinationSource;
          mergeTo = value;
        } else {
          mergeFrom = value;
          mergeTo = originalDestinationSource;
        }

        // TODO(jensj): Find out what the right thing to do is --- it probably
        // depends on what we do if read the same library twice - do we merge or
        // do we overwrite, and should we even support such a thing?

        // Merge coverage. Note that mergeFrom might be null.
        if (mergeTo.constantCoverageConstructors == null) {
          mergeTo.constantCoverageConstructors =
              mergeFrom?.constantCoverageConstructors;
        } else if (mergeFrom?.constantCoverageConstructors == null) {
          // Nothing to do.
        } else {
          // Both are non-null: Merge.
          mergeTo.constantCoverageConstructors!
              .addAll(mergeFrom!.constantCoverageConstructors!);
        }
      });
    }
  }

  void skipCanonicalNameReference() {
    readUInt30();
  }

  CanonicalName? readNullableCanonicalNameReference() {
    int index = readUInt30();
    if (index == 0) return null;
    return _linkTable[index - 1];
  }

  CanonicalName readNonNullCanonicalNameReference() {
    CanonicalName? canonicalName = readNullableCanonicalNameReference();
    if (canonicalName == null) {
      throw new StateError('No canonical name found.');
    }
    return canonicalName;
  }

  CanonicalName? getNullableCanonicalNameReferenceFromInt(int index) {
    if (index == 0) return null;
    return _linkTable[index - 1];
  }

  Reference? readNullableLibraryReference() {
    CanonicalName? canonicalName = readNullableCanonicalNameReference();
    return canonicalName?.reference;
  }

  Reference readNonNullLibraryReference() {
    CanonicalName? canonicalName = readNullableCanonicalNameReference();
    if (canonicalName != null) return canonicalName.reference;
    throw 'Expected a library reference to be valid but was `null`.';
  }

  LibraryDependency readLibraryDependencyReference() {
    int index = readUInt30();
    return _currentLibrary!.dependencies[index];
  }

  Reference readNonNullClassReference() {
    CanonicalName? name = readNullableCanonicalNameReference();
    if (name == null) {
      throw 'Expected a class reference to be valid but was `null`.';
    }
    return name.reference;
  }

  Reference readNonNullExtensionTypeDeclarationReference() {
    CanonicalName? name = readNullableCanonicalNameReference();
    if (name == null) {
      throw 'Expected an extension type declaration reference to be valid but '
          'was `null`.';
    }
    return name.reference;
  }

  void skipMemberReference() {
    skipCanonicalNameReference();
  }

  Reference? readNullableMemberReference() {
    CanonicalName? name = readNullableCanonicalNameReference();
    return name?.reference;
  }

  Reference readNonNullMemberReference() {
    CanonicalName? name = readNullableCanonicalNameReference();
    if (name == null) {
      throw 'Expected a member reference to be valid but was `null`.';
    }
    return name.reference;
  }

  Reference readNonNullInstanceMemberReference() {
    Reference reference = readNonNullMemberReference();
    readNullableMemberReference(); // Skip origin
    return reference;
  }

  Reference? getNullableMemberReferenceFromInt(int index) {
    return getNullableCanonicalNameReferenceFromInt(index)?.reference;
  }

  Reference readNonNullTypedefReference() {
    return readNonNullCanonicalNameReference().reference;
  }

  Name readName() {
    final int stringReference = readUInt30();
    assert(stringReference < (1 << 30));
    final String text = _stringTable[stringReference];
    final bool isPrivate = text.isNotEmpty && text.codeUnitAt(0) == $_;
    final int libraryReferenceIndex;
    final int nameCacheIndex;

    if (isPrivate) {
      // "Raw" reference index of 0 means null which we don't allow.
      libraryReferenceIndex = readUInt30();
      if (libraryReferenceIndex == 0) {
        throw 'Expected a library reference to be valid but was `null`.';
      }

      // Check cache using the upper bits for the library reference.
      nameCacheIndex = stringReference | ((libraryReferenceIndex) << 30);
    } else {
      // the 0 will be unused but we need to assign it.
      libraryReferenceIndex = 0;
      nameCacheIndex = stringReference;
    }

    final Name? cached = _nameCache[nameCacheIndex];
    if (cached != null) {
      return cached;
    }

    // Not in cache. Create it and cache it.
    final Name name;
    if (isPrivate) {
      // libraryReferenceIndex was checked to be > 0 so we get a canonical name.
      final CanonicalName canonicalName =
          getNullableCanonicalNameReferenceFromInt(libraryReferenceIndex)!;
      final Reference libraryReference = canonicalName.reference;
      name = new Name.byReference(text, libraryReference);
    } else {
      name = new Name(text);
    }
    _nameCache[nameCacheIndex] = name;
    return name;
  }

  Library readLibrary(Component component, int endOffset) {
    // Read index.
    int savedByteOffset = _byteOffset;

    // There is a field for the procedure count.
    _byteOffset = endOffset - (1) * 4;
    int procedureCount = readUint32();

    // There is a field for the procedure count, that number + 1 (for the end)
    // offsets, and then the class count (i.e. procedure count + 3 fields).
    _byteOffset = endOffset - (procedureCount + 3) * 4;
    int classCount = readUint32();
    List<int> procedureOffsets = new List<int>.generate(
        procedureCount + 1, (int index) => _componentStartOffset + readUint32(),
        growable: false);

    // There is a field for the procedure count, that number + 1 (for the end)
    // offsets, then the class count and that number + 1 (for the end) offsets.
    // (i.e. procedure count + class count + 4 fields).
    _byteOffset = endOffset - (procedureCount + classCount + 4) * 4;
    List<int> classOffsets = new List<int>.generate(
        classCount + 1, (int index) => _componentStartOffset + readUint32(),
        growable: false);
    _byteOffset = savedByteOffset;

    int flags = readByte();

    int languageVersionMajor = readUInt30();
    int languageVersionMinor = readUInt30();

    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    Reference reference = canonicalName.reference;
    Library? library = reference.node as Library?;
    String? name = readStringOrNullIfEmpty();

    // TODO(jensj): We currently save (almost the same) uri twice.
    Uri fileUri = readUriReference();

    if (alwaysCreateNewNamedNodes) {
      library = null;
    }
    if (library == null) {
      library = new Library(Uri.parse(canonicalName.name),
          reference: reference, fileUri: fileUri);
      component.libraries.add(library..parent = component);
    }
    _currentLibrary = library;

    List<String>? problemsAsJson = readListOfStrings();

    library.flags = flags;
    library.setLanguageVersion(
        new Version(languageVersionMajor, languageVersionMinor));
    library.name = name;
    library.fileUri = fileUri;
    library.problemsAsJson = problemsAsJson;

    assert(() {
      debugPath.add(library!.name ?? library.importUri.toString());
      return true;
    }());

    library.annotations = readAnnotationList(library);
    _readLibraryDependencies(library);
    _readAdditionalExports(library);
    _readLibraryParts(library);
    _readTypedefList(library);
    _readClassList(library, classOffsets);
    _readExtensionList(library);
    _readExtensionTypeDeclarationList(library);
    library.fieldsInternal = _readFieldList(library);
    library.proceduresInternal = _readProcedureList(library, procedureOffsets);

    assert(((_) => true)(debugPath.removeLast()));
    _currentLibrary = null;
    return library;
  }

  void _readTypedefList(Library library) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      library.typedefsInternal = emptyListOfTypedef;
    } else {
      library.typedefsInternal = new List<Typedef>.generate(
          length, (int index) => readTypedef()..parent = library,
          growable: useGrowableLists);
    }
  }

  void _readClassList(Library library, List<int> classOffsets) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      library.classesInternal = emptyListOfClass;
    } else {
      library.classesInternal = new List<Class>.generate(length, (int index) {
        _byteOffset = classOffsets[index];
        return readClass(classOffsets[index + 1])..parent = library;
      }, growable: useGrowableLists);
      _byteOffset = classOffsets.last;
    }
  }

  void _readExtensionList(Library library) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      library.extensionsInternal = emptyListOfExtension;
    } else {
      library.extensionsInternal = new List<Extension>.generate(
          length, (int index) => readExtension()..parent = library,
          growable: useGrowableLists);
    }
  }

  void _readExtensionTypeDeclarationList(Library library) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      library.extensionTypeDeclarationsInternal =
          emptyListOfExtensionTypeDeclaration;
    } else {
      library.extensionTypeDeclarationsInternal =
          new List<ExtensionTypeDeclaration>.generate(length,
              (int index) => readExtensionTypeDeclaration()..parent = library,
              growable: useGrowableLists);
    }
  }

  List<Field> _readFieldList(TreeNode parent) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfField;
    }
    return new List<Field>.generate(
        length, (int index) => readField()..parent = parent,
        growable: useGrowableLists);
  }

  List<Procedure> _readProcedureList(
      TreeNode parent, List<int> procedureOffsets) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfProcedure;
    }
    List<Procedure> list = new List<Procedure>.generate(length, (int index) {
      _byteOffset = procedureOffsets[index];
      return readProcedure(procedureOffsets[index + 1])..parent = parent;
    }, growable: useGrowableLists);
    _byteOffset = procedureOffsets.last;
    return list;
  }

  List<Procedure> _readProcedureListWithoutOffsets(TreeNode parent) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfProcedure;
    }
    List<Procedure> list = new List<Procedure>.generate(length, (int index) {
      return readProcedure(/* no end offset = */ -1)..parent = parent;
    }, growable: useGrowableLists);
    return list;
  }

  void _readLibraryDependencies(Library library) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      library.dependencies = emptyListOfLibraryDependency;
    } else {
      library.dependencies = new List<LibraryDependency>.generate(
          length, (int index) => readLibraryDependency()..parent = library,
          growable: useGrowableLists);
    }
  }

  LibraryDependency readLibraryDependency() {
    int fileOffset = readOffset();
    int flags = readByte();
    List<Expression> annotations = readExpressionList();
    Reference targetLibrary = readNonNullLibraryReference();
    String? prefixName = readStringOrNullIfEmpty();
    List<Combinator> names = readCombinatorList();
    return new LibraryDependency.byReference(
        flags, annotations, targetLibrary, prefixName, names)
      ..fileOffset = fileOffset;
  }

  void _readAdditionalExports(Library library) {
    int numExportedReference = readUInt30();
    if (numExportedReference != 0) {
      library.additionalExports.clear();
      for (int i = 0; i < numExportedReference; i++) {
        CanonicalName exportedName = readNonNullCanonicalNameReference();
        Reference reference = exportedName.reference;
        library.additionalExports.add(reference);
      }
    }
  }

  Combinator readCombinator() {
    bool isShow = readByte() == 1;
    List<String> names = readStringReferenceList();
    return new Combinator(isShow, names);
  }

  List<Combinator> readCombinatorList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfCombinator;
    }
    return new List<Combinator>.generate(length, (_) => readCombinator(),
        growable: useGrowableLists);
  }

  void _readLibraryParts(Library library) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      library.parts = emptyListOfLibraryPart;
    } else {
      library.parts = new List<LibraryPart>.generate(
          length, (int index) => readLibraryPart()..parent = library,
          growable: useGrowableLists);
    }
  }

  LibraryPart readLibraryPart() {
    List<Expression> annotations = readExpressionList();
    String partUri = readStringReference();
    return new LibraryPart(annotations, partUri);
  }

  Typedef readTypedef() {
    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    Reference reference = canonicalName.reference;
    Typedef? node = reference.node as Typedef?;
    if (alwaysCreateNewNamedNodes) {
      node = null;
    }
    Uri fileUri = readUriReference();
    int fileOffset = readOffset();
    String name = readStringReference();
    if (node == null) {
      node = new Typedef(name, null, reference: reference, fileUri: fileUri);
    }
    node.annotations = readAnnotationList(node);
    readAndPushTypeParameterList(node.typeParameters, node);
    DartType type = readDartType();
    typeParameterStack.length = 0;
    variableStack.length = 0;
    node.fileOffset = fileOffset;
    node.name = name;
    node.fileUri = fileUri;
    node.type = type;
    return node;
  }

  Class readClass(int endOffset) {
    int tag = readByte();
    assert(tag == Tag.Class);

    // Read index.
    int savedByteOffset = _byteOffset;
    // There is a field for the procedure count.
    _byteOffset = endOffset - (1) * 4;
    int procedureCount = readUint32();
    // There is a field for the procedure count, that number + 1 (for the end)
    // offsets (i.e. procedure count + 2 fields).
    _byteOffset = endOffset - (procedureCount + 2) * 4;
    List<int> procedureOffsets = new List<int>.generate(
        procedureCount + 1, (_) => _componentStartOffset + readUint32(),
        growable: false);
    _byteOffset = savedByteOffset;

    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    Reference reference = canonicalName.reference;
    Class? node = reference.node as Class?;
    if (alwaysCreateNewNamedNodes) {
      node = null;
    }
    Uri fileUri = readUriReference();
    int startFileOffset = readOffset();
    int fileOffset = readOffset();
    int fileEndOffset = readOffset();
    int flags = readUInt30();
    String name = readStringReference();
    if (node == null) {
      node = new Class(name: name, reference: reference, fileUri: fileUri)
        ..dirty = false;
    }

    node.startFileOffset = startFileOffset;
    node.fileOffset = fileOffset;
    node.fileEndOffset = fileEndOffset;
    node.flags = flags;
    List<Expression> annotations = readAnnotationList(node);
    assert(() {
      debugPath.add(name);
      return true;
    }());

    assert(typeParameterStack.length == 0);

    readAndPushTypeParameterList(node.typeParameters, node);
    Supertype? supertype = readSupertypeOption();
    Supertype? mixedInType = readSupertypeOption();
    node.implementedTypes = readSupertypeList();
    if (_disableLazyClassReading) {
      readClassPartialContent(node, procedureOffsets);
    } else {
      _setLazyLoadClass(node, procedureOffsets);
    }

    typeParameterStack.length = 0;
    assert(() {
      debugPath.removeLast();
      return true;
    }());
    node.name = name;
    node.fileUri = fileUri;
    node.annotations = annotations;
    node.supertype = supertype;
    node.mixedInType = mixedInType;

    _byteOffset = endOffset;

    return node;
  }

  Extension readExtension() {
    int tag = readByte();
    assert(tag == Tag.Extension);

    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    Reference reference = canonicalName.reference;
    Extension? node = reference.node as Extension?;
    if (alwaysCreateNewNamedNodes) {
      node = null;
    }

    String name = readStringReference();
    assert(() {
      debugPath.add(name);
      return true;
    }());

    List<Expression> annotations = readAnnotationList();

    Uri fileUri = readUriReference();

    if (node == null) {
      node = new Extension(name: name, reference: reference, fileUri: fileUri);
    }
    node.annotations = annotations;
    setParents(annotations, node);

    node.fileOffset = readOffset();

    node.flags = readByte();

    readAndPushTypeParameterList(node.typeParameters, node);
    DartType onType = readDartType();

    typeParameterStack.length = 0;

    node.name = name;
    node.fileUri = fileUri;
    node.onType = onType;

    node.memberDescriptors = _readExtensionMemberDescriptorList();

    return node;
  }

  List<ExtensionMemberDescriptor> _readExtensionMemberDescriptorList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use a
      // constant one for the empty list.
      return emptyListOfExtensionMemberDescriptor;
    }
    return new List<ExtensionMemberDescriptor>.generate(
        length, (_) => _readExtensionMemberDescriptor(),
        growable: useGrowableLists);
  }

  ExtensionMemberDescriptor _readExtensionMemberDescriptor() {
    Name name = readName();
    int kind = readByte();
    int flags = readByte();
    CanonicalName? memberName = readNullableCanonicalNameReference();
    CanonicalName? tearOffName = readNullableCanonicalNameReference();
    return new ExtensionMemberDescriptor(
        name: name,
        kind: ExtensionMemberKind.values[kind],
        memberReference: memberName?.reference,
        tearOffReference: tearOffName?.reference)
      ..flags = flags;
  }

  ExtensionTypeDeclaration readExtensionTypeDeclaration() {
    int tag = readByte();
    assert(tag == Tag.ExtensionTypeDeclaration, "Unexpected tag $tag");

    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    Reference reference = canonicalName.reference;
    ExtensionTypeDeclaration? node =
        reference.node as ExtensionTypeDeclaration?;
    if (alwaysCreateNewNamedNodes) {
      node = null;
    }

    String name = readStringReference();
    assert(() {
      debugPath.add(name);
      return true;
    }());

    List<Expression> annotations = readAnnotationList();

    Uri fileUri = readUriReference();

    if (node == null) {
      node = new ExtensionTypeDeclaration(
          name: name, reference: reference, fileUri: fileUri);
    }
    node.annotations = annotations;
    setParents(annotations, node);

    node.fileOffset = readOffset();

    node.flags = readByte();

    readAndPushTypeParameterList(node.typeParameters, node);
    DartType representationType = readDartType();
    String representationName = readStringReference();
    List<TypeDeclarationType> implements =
        _readExtensionTypeDeclarationImplementsList();

    node.proceduresInternal = _readProcedureListWithoutOffsets(node);
    typeParameterStack.length = 0;

    node.name = name;
    node.fileUri = fileUri;
    node.declaredRepresentationType = representationType;
    node.representationName = representationName;

    node.implements = implements;

    node.memberDescriptors = _readExtensionTypeMemberDescriptorList();

    return node;
  }

  List<TypeDeclarationType> _readExtensionTypeDeclarationImplementsList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use a
      // constant one for the empty list.
      return emptyListOfTypeDeclarationType;
    }
    return new List<TypeDeclarationType>.generate(
        length, (_) => readDartType() as TypeDeclarationType,
        growable: useGrowableLists);
  }

  List<ExtensionTypeMemberDescriptor> _readExtensionTypeMemberDescriptorList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use a
      // constant one for the empty list.
      return emptyListOfExtensionTypeMemberDescriptor;
    }
    return new List<ExtensionTypeMemberDescriptor>.generate(
        length, (_) => _readExtensionTypeMemberDescriptor(),
        growable: useGrowableLists);
  }

  ExtensionTypeMemberDescriptor _readExtensionTypeMemberDescriptor() {
    Name name = readName();
    int kind = readByte();
    int flags = readByte();
    CanonicalName? memberName = readNullableCanonicalNameReference();
    CanonicalName? tearOffName = readNullableCanonicalNameReference();
    return new ExtensionTypeMemberDescriptor(
        name: name,
        kind: ExtensionTypeMemberKind.values[kind],
        memberReference: memberName?.reference,
        tearOffReference: tearOffName?.reference)
      ..flags = flags;
  }

  /// Reads the partial content of a class, namely fields, procedures,
  /// constructors and redirecting factory constructors.
  void readClassPartialContent(Class node, List<int> procedureOffsets) {
    node.fieldsInternal = _readFieldList(node);
    _readConstructorList(node);
    node.proceduresInternal = _readProcedureList(node, procedureOffsets);
  }

  void _readConstructorList(Class node) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use a
      // constant one for the empty list.
      node.constructorsInternal = emptyListOfConstructor;
    } else {
      node.constructorsInternal = new List<Constructor>.generate(
          length, (int index) => readConstructor()..parent = node,
          growable: useGrowableLists);
    }
  }

  /// Set the lazyBuilder on the class so it can be lazy loaded in the future.
  void _setLazyLoadClass(Class node, List<int> procedureOffsets) {
    final int savedByteOffset = _byteOffset;
    final int componentStartOffset = _componentStartOffset;
    final Library? currentLibrary = _currentLibrary;
    node.lazyBuilder = () {
      _byteOffset = savedByteOffset;
      _currentLibrary = currentLibrary;
      assert(typeParameterStack.isEmpty);
      _componentStartOffset = componentStartOffset;
      typeParameterStack.addAll(node.typeParameters);

      readClassPartialContent(node, procedureOffsets);
      typeParameterStack.length = 0;
    };
  }

  int getAndResetTransformerFlags() {
    int flags = _transformerFlags;
    _transformerFlags = 0;
    return flags;
  }

  /// Adds the given flag to the current [Member.transformerFlags].
  void addTransformerFlag(int flags) {
    _transformerFlags |= flags;
  }

  Field readField() {
    int tag = readByte();
    assert(tag == Tag.Field);
    CanonicalName fieldCanonicalName = readNonNullCanonicalNameReference();
    Reference fieldReference = fieldCanonicalName.reference;
    CanonicalName getterCanonicalName = readNonNullCanonicalNameReference();
    Reference getterReference = getterCanonicalName.reference;
    CanonicalName? setterCanonicalName = readNullableCanonicalNameReference();
    Reference? setterReference = setterCanonicalName?.reference;
    Field? node = fieldReference.node as Field?;
    if (alwaysCreateNewNamedNodes) {
      node = null;
    }
    Uri fileUri = readUriReference();
    int fileOffset = readOffset();
    int fileEndOffset = readOffset();
    int flags = readUInt30();
    Name name = readName();
    if (node == null) {
      if (setterReference != null) {
        node = new Field.mutable(name,
            fieldReference: fieldReference,
            getterReference: getterReference,
            setterReference: setterReference,
            fileUri: fileUri);
      } else {
        node = new Field.immutable(name,
            fieldReference: fieldReference,
            getterReference: getterReference,
            fileUri: fileUri);
      }
    }
    List<Expression> annotations = readAnnotationList(node);
    assert(() {
      debugPath.add(name.text);
      return true;
    }());
    DartType type = readDartType();
    Expression? initializer = readExpressionOption();
    int transformerFlags = getAndResetTransformerFlags();
    assert(((_) => true)(debugPath.removeLast()));
    node.fileOffset = fileOffset;
    node.fileEndOffset = fileEndOffset;
    node.flags = flags;
    node.name = name;
    node.fileUri = fileUri;
    node.annotations = annotations;
    node.type = type;
    node.initializer = initializer;
    node.initializer?.parent = node;
    node.transformerFlags = transformerFlags;
    return node;
  }

  Constructor readConstructor() {
    int tag = readByte();
    assert(tag == Tag.Constructor);
    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    Reference reference = canonicalName.reference;
    Constructor? node = reference.node as Constructor?;
    if (alwaysCreateNewNamedNodes) {
      node = null;
    }
    Uri fileUri = readUriReference();
    int startFileOffset = readOffset();
    int fileOffset = readOffset();
    int fileEndOffset = readOffset();
    int flags = readByte();
    Name name = readName();
    List<Expression> annotations = readAnnotationList();
    assert(() {
      debugPath.add(name.text);
      return true;
    }());
    FunctionNode function = readFunctionNode();
    if (node == null) {
      node = new Constructor(function,
          reference: reference, name: name, fileUri: fileUri);
    }
    pushVariableDeclarations(function.positionalParameters);
    pushVariableDeclarations(function.namedParameters);
    _readInitializers(node);
    variableStack.length = 0;
    int transformerFlags = getAndResetTransformerFlags();
    assert(((_) => true)(debugPath.removeLast()));
    node.startFileOffset = startFileOffset;
    node.fileOffset = fileOffset;
    node.fileEndOffset = fileEndOffset;
    node.flags = flags;
    node.name = name;
    node.fileUri = fileUri;
    node.annotations = annotations;
    setParents(annotations, node);
    node.function = function..parent = node;
    node.transformerFlags = transformerFlags;
    return node;
  }

  Procedure readProcedure(int endOffset) {
    int tag = readByte();
    assert(tag == Tag.Procedure);
    CanonicalName canonicalName = readNonNullCanonicalNameReference();
    Reference reference = canonicalName.reference;
    Procedure? node;
    if (!alwaysCreateNewNamedNodes) {
      node = reference.node as Procedure?;
    }
    Uri fileUri = readUriReference();
    int startFileOffset = readOffset();
    int fileOffset = readOffset();
    int fileEndOffset = readOffset();
    int kindIndex = readByte();
    ProcedureKind kind = ProcedureKind.values[kindIndex];
    ProcedureStubKind stubKind = ProcedureStubKind.values[readByte()];
    int flags = readUInt30();
    Name name = readName();
    List<Expression> annotations = readAnnotationList();
    assert(() {
      debugPath.add(name.text);
      return true;
    }());

    int functionNodeSize = endOffset - _byteOffset;
    // Read small factories and extension type declaration procedures
    // (where `endOffset == -1`) up front. Postpone everything else.
    bool readFunctionNodeNow = endOffset == -1 ||
        (kind == ProcedureKind.Factory && functionNodeSize <= 50) ||
        _disableLazyReading;
    Reference? stubTargetReference = readNullableMemberReference();
    FunctionType? signatureType = readDartTypeOption() as FunctionType?;
    FunctionNode function = readFunctionNode(
        lazyLoadBody: !readFunctionNodeNow, outerEndOffset: endOffset);
    if (node == null) {
      node = new Procedure(name, kind, function,
          reference: reference, fileUri: fileUri);
    } else {
      assert(node.kind == kind);
    }
    int transformerFlags = getAndResetTransformerFlags();
    assert(((_) => true)(debugPath.removeLast()));
    node.fileStartOffset = startFileOffset;
    node.fileOffset = fileOffset;
    node.fileEndOffset = fileEndOffset;
    node.flags = flags;
    node.name = name;
    node.fileUri = fileUri;
    node.annotations = annotations;
    setParents(annotations, node);
    node.function = function..parent = node;
    node.setTransformerFlagsWithoutLazyLoading(transformerFlags);
    node.stubKind = stubKind;
    node.stubTargetReference = stubTargetReference;
    node.signatureType = signatureType;

    assert((node.stubKind == ProcedureStubKind.ConcreteForwardingStub &&
            node.stubTargetReference != null) ||
        !(node.isForwardingStub && node.function.body != null));
    assert(!(node.isMemberSignature && node.stubTargetReference == null),
        "No member signature origin for member signature $node.");
    return node;
  }

  void _readInitializers(Constructor constructor) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use a
      // constant one for the empty list.
      constructor.initializers = emptyListOfInitializer;
    } else {
      constructor.initializers = new List<Initializer>.generate(
          length, (int index) => readInitializer()..parent = constructor,
          growable: useGrowableLists);
    }
  }

  Initializer readInitializer() {
    int tag = readByte();
    bool isSynthetic = readByte() == 1;
    switch (tag) {
      // 52.71% (43.80% - 59.02%).
      case Tag.FieldInitializer:
        return _readFieldInitializer(isSynthetic);

      // 42.01% (28.38% - 55.93%)
      case Tag.SuperInitializer:
        return _readSuperInitializer(isSynthetic);

      // 4.69% (0.00% - 16.00%).
      case Tag.AssertInitializer:
        return _readAssertInitializer();

      // The rest is < 2% on average in sampled dills.
      case Tag.InvalidInitializer:
        return _readInvalidInitializer();
      case Tag.RedirectingInitializer:
        return _readRedirectingInitializer();
      case Tag.LocalInitializer:
        return _readLocalInitializer();
      default:
        throw fail('unexpected initializer tag: $tag');
    }
  }

  Initializer _readInvalidInitializer() {
    return new InvalidInitializer();
  }

  Initializer _readFieldInitializer(bool isSynthetic) {
    int offset = readOffset();
    Reference reference = readNonNullMemberReference();
    Expression value = readExpression();
    return new FieldInitializer.byReference(reference, value)
      ..isSynthetic = isSynthetic
      ..fileOffset = offset;
  }

  Initializer _readSuperInitializer(bool isSynthetic) {
    int offset = readOffset();
    Reference reference = readNonNullMemberReference();
    Arguments arguments = readArguments();
    return new SuperInitializer.byReference(reference, arguments)
      ..isSynthetic = isSynthetic
      ..fileOffset = offset;
  }

  Initializer _readRedirectingInitializer() {
    int offset = readOffset();
    return new RedirectingInitializer.byReference(
        readNonNullMemberReference(), readArguments())
      ..fileOffset = offset;
  }

  Initializer _readLocalInitializer() {
    return new LocalInitializer(readAndPushVariableDeclaration());
  }

  Initializer _readAssertInitializer() {
    return new AssertInitializer(readStatement() as AssertStatement);
  }

  FunctionNode readFunctionNode(
      {bool lazyLoadBody = false, int outerEndOffset = -1}) {
    int tag = readByte();
    assert(tag == Tag.FunctionNode);
    int offset = readOffset();
    int endOffset = readOffset();
    AsyncMarker asyncMarker = AsyncMarker.values[readByte()];
    AsyncMarker dartAsyncMarker = AsyncMarker.values[readByte()];
    int typeParameterStackHeight = typeParameterStack.length;
    List<TypeParameter> typeParameters = readAndPushTypeParameterList();
    readUInt30(); // total parameter count.
    int requiredParameterCount = readUInt30();
    int variableStackHeight = variableStack.length;
    List<VariableDeclaration> positional = readAndPushVariableDeclarationList();
    List<VariableDeclaration> named = readAndPushVariableDeclarationList();
    DartType returnType = readDartType();
    DartType? futureValueType = readDartTypeOption();
    RedirectingFactoryTarget? redirectingFactoryTarget;
    if (readAndCheckOptionTag()) {
      Reference? targetReference = readNullableMemberReference();
      List<DartType>? typeArguments;
      if (readAndCheckOptionTag()) {
        typeArguments = readDartTypeList();
      }
      if (readAndCheckOptionTag()) {
        assert(targetReference == null && typeArguments == null);
        String errorMessage = readStringReference();
        redirectingFactoryTarget =
            new RedirectingFactoryTarget.error(errorMessage);
      } else {
        assert(targetReference != null && typeArguments != null);
        redirectingFactoryTarget = new RedirectingFactoryTarget.byReference(
            targetReference!, typeArguments!);
      }
    }

    int oldLabelStackBase = labelStackBase;
    int oldSwitchCaseStackBase = switchCaseStackBase;

    if (lazyLoadBody && outerEndOffset > 0) {
      lazyLoadBody = outerEndOffset - _byteOffset >
          2; // e.g. outline has Tag.Something and Tag.EmptyStatement
    }

    Statement? body;
    if (!lazyLoadBody) {
      labelStackBase = labelStack.length;
      switchCaseStackBase = switchCaseStack.length;
      body = readStatementOption();
    }

    FunctionNode result = new FunctionNode(body,
        typeParameters: typeParameters,
        requiredParameterCount: requiredParameterCount,
        positionalParameters: positional,
        namedParameters: named,
        returnType: returnType,
        asyncMarker: asyncMarker,
        dartAsyncMarker: dartAsyncMarker,
        emittedValueType: futureValueType)
      ..fileOffset = offset
      ..fileEndOffset = endOffset
      ..redirectingFactoryTarget = redirectingFactoryTarget;

    if (lazyLoadBody) {
      _setLazyLoadFunction(result, oldLabelStackBase, oldSwitchCaseStackBase,
          variableStackHeight);
    }

    labelStackBase = oldLabelStackBase;
    switchCaseStackBase = oldSwitchCaseStackBase;
    variableStack.length = variableStackHeight;
    typeParameterStack.length = typeParameterStackHeight;

    return result;
  }

  void _setLazyLoadFunction(FunctionNode result, int oldLabelStackBase,
      int oldSwitchCaseStackBase, int variableStackHeight) {
    final int savedByteOffset = _byteOffset;
    final int componentStartOffset = _componentStartOffset;
    final List<TypeParameter> typeParameters =
        typeParameterStack.cast<TypeParameter>().toList();
    final List<VariableDeclaration> variables = variableStack.toList();
    final Library currentLibrary = _currentLibrary!;
    result.lazyBuilder = () {
      _byteOffset = savedByteOffset;
      _currentLibrary = currentLibrary;
      typeParameterStack.clear();
      typeParameterStack.addAll(typeParameters);
      variableStack.clear();
      variableStack.addAll(variables);
      _componentStartOffset = componentStartOffset;

      result.body = readStatementOption();
      result.body?.parent = result;
      labelStackBase = oldLabelStackBase;
      switchCaseStackBase = oldSwitchCaseStackBase;
      variableStack.length = variableStackHeight;
      typeParameterStack.clear();
      TreeNode? parent = result.parent;
      if (parent is Procedure) {
        parent.transformerFlags |= getAndResetTransformerFlags();
      }
    };
  }

  void pushVariableDeclaration(VariableDeclaration variable) {
    variableStack.add(variable);
  }

  void pushVariableDeclarations(List<VariableDeclaration> variables) {
    variableStack.addAll(variables);
  }

  VariableDeclaration readVariableReference() {
    readUInt30(); // offset of the variable declaration in the binary.
    return _readVariableReferenceInternal();
  }

  VariableDeclaration _readVariableReferenceInternal() {
    int index = readUInt30();
    if (index >= variableStack.length) {
      throw fail('Unexpected variable index: $index. '
          'Current variable count: ${variableStack.length}.');
    }
    return variableStack[index];
  }

  LogicalExpressionOperator logicalOperatorToEnum(int index) {
    switch (index) {
      case 0:
        return LogicalExpressionOperator.AND;
      case 1:
        return LogicalExpressionOperator.OR;
      default:
        throw fail('unexpected logical operator index: $index');
    }
  }

  List<Expression> readExpressionList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use a
      // constant one for the empty list.
      return emptyListOfExpression;
    }
    return new List<Expression>.generate(length, (_) => readExpression(),
        growable: useGrowableLists);
  }

  Expression? readExpressionOption() {
    return readAndCheckOptionTag() ? readExpression() : null;
  }

  Expression readExpression() {
    int tagByte = readByte();
    int tag = tagByte & Tag.SpecializedTagHighBits == Tag.SpecializedTagHighBits
        ? (tagByte & Tag.SpecializedTagMask)
        : tagByte;
    switch (tag) {
      // 18.57% (13.56% - 23.28%).
      case Tag.SpecializedVariableGet:
        return _readSpecializedVariableGet(tagByte);

      // 12.02% (9.14% - 14.14%).
      case Tag.InstanceGet:
        return _readInstanceGet();

      // 10.61% (6.82% - 14.13%).
      case Tag.ThisExpression:
        return _readThisLiteral();

      // 10.19% (6.51% - 15.46%).
      case Tag.ConstantExpression:
        return _readConstantExpression();

      // 9.95% (5.96% - 13.10%).
      case Tag.InstanceInvocation:
        return _readInstanceInvocation();

      // 6.20% (2.67% - 12.88%)
      case Tag.StringLiteral:
        return _readStringLiteral();

      // 4.30% (1.89% - 5.58%).
      case Tag.VariableGet:
        return _readVariableGet();

      // 3.94% (2.48% - 6.29%).
      case Tag.StaticInvocation:
        return _readStaticInvocation();

      // 2.95% (1.58% - 5.31%).
      case Tag.SpecializedIntLiteral:
        return _readSpecializedIntLiteral(tagByte);

      // 2.92% (1.76% - 5.21%).
      case Tag.ConstructorInvocation:
        return _readConstructorInvocation();

      // The rest is < 2% on average in sampled dills.
      case Tag.LoadLibrary:
        return _readLoadLibrary();
      case Tag.CheckLibraryIsLoaded:
        return _readCheckLibraryIsLoaded();
      case Tag.InvalidExpression:
        return _readInvalidExpression();
      case Tag.VariableSet:
        return _readVariableSet();
      case Tag.SpecializedVariableSet:
        return _readSpecializedVariableSet(tagByte);
      case Tag.InstanceTearOff:
        return _readInstanceTearOff();
      case Tag.DynamicGet:
        return _readDynamicGet();
      case Tag.RecordIndexGet:
        return _readRecordIndexGet();
      case Tag.RecordNameGet:
        return _readRecordNameGet();
      case Tag.InstanceSet:
        return _readInstanceSet();
      case Tag.DynamicSet:
        return _readDynamicSet();
      case Tag.AbstractSuperPropertyGet:
        return _readAbstractSuperPropertyGet();
      case Tag.AbstractSuperPropertySet:
        return _readAbstractSuperPropertySet();
      case Tag.SuperPropertyGet:
        return _readSuperPropertyGet();
      case Tag.SuperPropertySet:
        return _readSuperPropertySet();
      case Tag.StaticGet:
        return _readStaticGet();
      case Tag.StaticTearOff:
        return _readStaticTearOff();
      case Tag.StaticSet:
        return _readStaticSet();
      case Tag.ConstructorTearOff:
        return _readConstructorTearOff();
      case Tag.TypedefTearOff:
        return _readTypedefTearOff();
      case Tag.RedirectingFactoryTearOff:
        return _readRedirectingFactoryTearOff();
      case Tag.InstanceGetterInvocation:
        return _readInstanceGetterInvocation();
      case Tag.DynamicInvocation:
        return _readDynamicInvocation();
      case Tag.FunctionInvocation:
        return _readFunctionInvocation();
      case Tag.FunctionTearOff:
        return _readFunctionTearOff();
      case Tag.LocalFunctionInvocation:
        return _readLocalFunctionInvocation();
      case Tag.EqualsNull:
        return _readEqualsNull();
      case Tag.EqualsCall:
        return _readEqualsCall();
      case Tag.AbstractSuperMethodInvocation:
        return _readAbstractSuperMethodInvocation();
      case Tag.SuperMethodInvocation:
        return _readSuperMethodInvocation();
      case Tag.ConstStaticInvocation:
        return _readConstStaticInvocation();
      case Tag.ConstConstructorInvocation:
        return _readConstConstructorInvocation();
      case Tag.Not:
        return _readNot();
      case Tag.NullCheck:
        return _readNullCheck();
      case Tag.LogicalExpression:
        return _readLogicalExpression();
      case Tag.ConditionalExpression:
        return _readConditionalExpression();
      case Tag.StringConcatenation:
        return _readStringConcatenation();
      case Tag.ListConcatenation:
        return _readListConcatenation();
      case Tag.SetConcatenation:
        return _readSetConcatenation();
      case Tag.MapConcatenation:
        return _readMapConcatenation();
      case Tag.InstanceCreation:
        return _readInstanceCreation();
      case Tag.FileUriExpression:
        return _readFileUriExpression();
      case Tag.IsExpression:
        return _readIsExpression();
      case Tag.AsExpression:
        return _readAsExpression();
      case Tag.PositiveIntLiteral:
        return _readPositiveIntLiteral();
      case Tag.NegativeIntLiteral:
        return _readNegativeIntLiteral();
      case Tag.BigIntLiteral:
        return _readBigIntLiteral();
      case Tag.DoubleLiteral:
        return _readDoubleLiteral();
      case Tag.TrueLiteral:
        return _readTrueLiteral();
      case Tag.FalseLiteral:
        return _readFalseLiteral();
      case Tag.NullLiteral:
        return _readNullLiteral();
      case Tag.SymbolLiteral:
        return _readSymbolLiteral();
      case Tag.TypeLiteral:
        return _readTypeLiteral();
      case Tag.Rethrow:
        return _readRethrow();
      case Tag.Throw:
        return _readThrow();
      case Tag.ListLiteral:
        return _readListLiteral();
      case Tag.ConstListLiteral:
        return _readConstListLiteral();
      case Tag.SetLiteral:
        return _readSetLiteral();
      case Tag.ConstSetLiteral:
        return _readConstSetLiteral();
      case Tag.MapLiteral:
        return _readMapLiteral();
      case Tag.ConstMapLiteral:
        return _readConstMapLiteral();
      case Tag.RecordLiteral:
        return _readRecordLiteral();
      case Tag.ConstRecordLiteral:
        return _readConstRecordLiteral();
      case Tag.AwaitExpression:
        return _readAwaitExpression();
      case Tag.FunctionExpression:
        return _readFunctionExpression();
      case Tag.Let:
        return _readLet();
      case Tag.BlockExpression:
        return _readBlockExpression();
      case Tag.Instantiation:
        return _readInstantiation();
      case Tag.SwitchExpression:
        return _readSwitchExpression();
      case Tag.PatternAssignment:
        return _readPatternAssignment();
      case Tag.FileUriConstantExpression:
        return _readFileUriConstantExpression();
      default:
        throw fail('unexpected expression tag: $tag');
    }
  }

  Expression _readLoadLibrary() {
    int offset = readOffset();
    return new LoadLibrary(readLibraryDependencyReference())
      ..fileOffset = offset;
  }

  Expression _readCheckLibraryIsLoaded() {
    int offset = readOffset();
    return new CheckLibraryIsLoaded(readLibraryDependencyReference())
      ..fileOffset = offset;
  }

  Expression _readInvalidExpression() {
    int offset = readOffset();
    return new InvalidExpression(
        readStringOrNullIfEmpty(), readExpressionOption())
      ..fileOffset = offset;
  }

  Expression _readVariableGet() {
    int offset = readOffset();
    return new VariableGet(readVariableReference(), readDartTypeOption())
      ..fileOffset = offset;
  }

  Expression _readSpecializedVariableGet(int tagByte) {
    int index = tagByte & Tag.SpecializedPayloadMask;
    int offset = readOffset();
    readUInt30(); // offset of the variable declaration in the binary.
    return new VariableGet(variableStack[index])..fileOffset = offset;
  }

  Expression _readVariableSet() {
    int offset = readOffset();
    return new VariableSet(readVariableReference(), readExpression())
      ..fileOffset = offset;
  }

  Expression _readSpecializedVariableSet(int tagByte) {
    int index = tagByte & Tag.SpecializedPayloadMask;
    int offset = readOffset();
    readUInt30(); // offset of the variable declaration in the binary.
    return new VariableSet(variableStack[index], readExpression())
      ..fileOffset = offset;
  }

  Expression _readInstanceGet() {
    InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
    int offset = readOffset();
    return new InstanceGet.byReference(kind, readExpression(), readName(),
        resultType: readDartType(),
        interfaceTargetReference: readNonNullInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readInstanceTearOff() {
    InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
    int offset = readOffset();
    return new InstanceTearOff.byReference(kind, readExpression(), readName(),
        resultType: readDartType(),
        interfaceTargetReference: readNonNullInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readDynamicGet() {
    DynamicAccessKind kind = DynamicAccessKind.values[readByte()];
    int offset = readOffset();
    return new DynamicGet(kind, readExpression(), readName())
      ..fileOffset = offset;
  }

  Expression _readRecordIndexGet() {
    int offset = readOffset();
    Expression receiver = readExpression();
    RecordType receiverType = readDartType() as RecordType;
    int index = readUInt30();
    return RecordIndexGet(receiver, receiverType, index)..fileOffset = offset;
  }

  Expression _readRecordNameGet() {
    int offset = readOffset();
    Expression receiver = readExpression();
    RecordType receiverType = readDartType() as RecordType;
    String name = readStringReference();
    return RecordNameGet(receiver, receiverType, name)..fileOffset = offset;
  }

  Expression _readInstanceSet() {
    InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
    int offset = readOffset();
    return new InstanceSet.byReference(
        kind, readExpression(), readName(), readExpression(),
        interfaceTargetReference: readNonNullInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readDynamicSet() {
    DynamicAccessKind kind = DynamicAccessKind.values[readByte()];
    int offset = readOffset();
    return new DynamicSet(kind, readExpression(), readName(), readExpression())
      ..fileOffset = offset;
  }

  Expression _readAbstractSuperPropertyGet() {
    int offset = readOffset();
    addTransformerFlag(TransformerFlag.superCalls);
    return new AbstractSuperPropertyGet.byReference(
        readName(), readNonNullInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readAbstractSuperPropertySet() {
    int offset = readOffset();
    addTransformerFlag(TransformerFlag.superCalls);
    return new AbstractSuperPropertySet.byReference(
        readName(), readExpression(), readNonNullInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readSuperPropertyGet() {
    int offset = readOffset();
    addTransformerFlag(TransformerFlag.superCalls);
    return new SuperPropertyGet.byReference(
        readName(), readNonNullInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readSuperPropertySet() {
    int offset = readOffset();
    addTransformerFlag(TransformerFlag.superCalls);
    return new SuperPropertySet.byReference(
        readName(), readExpression(), readNonNullInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readStaticGet() {
    int offset = readOffset();
    return new StaticGet.byReference(readNonNullMemberReference())
      ..fileOffset = offset;
  }

  Expression _readConstructorTearOff() {
    int offset = readOffset();
    Reference constructorReference = readNonNullMemberReference();
    return new ConstructorTearOff.byReference(constructorReference)
      ..fileOffset = offset;
  }

  Expression _readTypedefTearOff() {
    int offset = readOffset();
    List<StructuralParameter> structuralParameters =
        readAndPushStructuralParameterList();
    Expression expression = readExpression();
    List<DartType> typeArguments = readDartTypeList();
    typeParameterStack.length -= structuralParameters.length;
    return new TypedefTearOff(structuralParameters, expression, typeArguments)
      ..fileOffset = offset;
  }

  Expression _readRedirectingFactoryTearOff() {
    int offset = readOffset();
    Reference constructorReference = readNonNullMemberReference();
    return new RedirectingFactoryTearOff.byReference(constructorReference)
      ..fileOffset = offset;
  }

  Expression _readStaticTearOff() {
    int offset = readOffset();
    return new StaticTearOff.byReference(readNonNullMemberReference())
      ..fileOffset = offset;
  }

  Expression _readStaticSet() {
    int offset = readOffset();
    return new StaticSet.byReference(
        readNonNullMemberReference(), readExpression())
      ..fileOffset = offset;
  }

  Expression _readInstanceInvocation() {
    InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
    int flags = readByte();
    int offset = readOffset();
    return new InstanceInvocation.byReference(
        kind, readExpression(), readName(), readArguments(),
        functionType: readDartType() as FunctionType,
        interfaceTargetReference: readNonNullInstanceMemberReference())
      ..fileOffset = offset
      ..flags = flags;
  }

  Expression _readInstanceGetterInvocation() {
    InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
    int flags = readByte();
    int offset = readOffset();
    Expression receiver = readExpression();
    Name name = readName();
    Arguments arguments = readArguments();
    DartType functionType = readDartType();
    // `const DynamicType()` is used to encode a missing function type.
    assert(functionType is FunctionType || functionType is DynamicType,
        "Unexpected function type $functionType for InstanceGetterInvocation");
    Reference interfaceTargetReference = readNonNullInstanceMemberReference();
    return new InstanceGetterInvocation.byReference(
        kind, receiver, name, arguments,
        functionType: functionType is FunctionType ? functionType : null,
        interfaceTargetReference: interfaceTargetReference)
      ..fileOffset = offset
      ..flags = flags;
  }

  Expression _readDynamicInvocation() {
    DynamicAccessKind kind = DynamicAccessKind.values[readByte()];
    int flags = readByte();
    int offset = readOffset();
    return new DynamicInvocation(
        kind, readExpression(), readName(), readArguments())
      ..fileOffset = offset
      ..flags = flags;
  }

  Expression _readFunctionInvocation() {
    FunctionAccessKind kind = FunctionAccessKind.values[readByte()];
    int offset = readOffset();
    Expression receiver = readExpression();
    Arguments arguments = readArguments();
    DartType functionType = readDartType();
    // `const DynamicType()` is used to encode a missing function type.
    assert(functionType is FunctionType || functionType is DynamicType,
        "Unexpected function type $functionType for FunctionInvocation");
    return new FunctionInvocation(kind, receiver, arguments,
        functionType: functionType is FunctionType ? functionType : null)
      ..fileOffset = offset;
  }

  Expression _readFunctionTearOff() {
    int offset = readOffset();
    return new FunctionTearOff(readExpression())..fileOffset = offset;
  }

  Expression _readLocalFunctionInvocation() {
    int offset = readOffset();
    VariableDeclaration variable = readVariableReference();
    return new LocalFunctionInvocation(variable, readArguments(),
        functionType: readDartType() as FunctionType)
      ..fileOffset = offset;
  }

  Expression _readEqualsNull() {
    int offset = readOffset();
    return new EqualsNull(readExpression())..fileOffset = offset;
  }

  Expression _readEqualsCall() {
    int offset = readOffset();
    return new EqualsCall.byReference(readExpression(), readExpression(),
        functionType: readDartType() as FunctionType,
        interfaceTargetReference: readNonNullInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readAbstractSuperMethodInvocation() {
    int offset = readOffset();
    addTransformerFlag(TransformerFlag.superCalls);
    return new AbstractSuperMethodInvocation.byReference(
        readName(), readArguments(), readNonNullInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readSuperMethodInvocation() {
    int offset = readOffset();
    addTransformerFlag(TransformerFlag.superCalls);
    return new SuperMethodInvocation.byReference(
        readName(), readArguments(), readNonNullInstanceMemberReference())
      ..fileOffset = offset;
  }

  Expression _readStaticInvocation() {
    int offset = readOffset();
    return new StaticInvocation.byReference(
        readNonNullMemberReference(), readArguments(),
        isConst: false)
      ..fileOffset = offset;
  }

  Expression _readConstStaticInvocation() {
    int offset = readOffset();
    return new StaticInvocation.byReference(
        readNonNullMemberReference(), readArguments(),
        isConst: true)
      ..fileOffset = offset;
  }

  Expression _readConstructorInvocation() {
    int offset = readOffset();
    return new ConstructorInvocation.byReference(
        readNonNullMemberReference(), readArguments(),
        isConst: false)
      ..fileOffset = offset;
  }

  Expression _readConstConstructorInvocation() {
    int offset = readOffset();
    return new ConstructorInvocation.byReference(
        readNonNullMemberReference(), readArguments(),
        isConst: true)
      ..fileOffset = offset;
  }

  Expression _readNot() {
    int offset = readOffset();
    return new Not(readExpression())..fileOffset = offset;
  }

  Expression _readNullCheck() {
    int offset = readOffset();
    return new NullCheck(readExpression())..fileOffset = offset;
  }

  Expression _readLogicalExpression() {
    int offset = readOffset();
    return new LogicalExpression(
        readExpression(), logicalOperatorToEnum(readByte()), readExpression())
      ..fileOffset = offset;
  }

  Expression _readConditionalExpression() {
    int offset = readOffset();
    return new ConditionalExpression(
        readExpression(),
        readExpression(),
        readExpression(),
        // TODO(johnniwinther): Change this to use `readDartType`.
        readDartTypeOption()!)
      ..fileOffset = offset;
  }

  Expression _readStringConcatenation() {
    int offset = readOffset();
    return new StringConcatenation(readExpressionList())..fileOffset = offset;
  }

  Expression _readListConcatenation() {
    int offset = readOffset();
    DartType typeArgument = readDartType();
    return new ListConcatenation(readExpressionList(),
        typeArgument: typeArgument)
      ..fileOffset = offset;
  }

  Expression _readSetConcatenation() {
    int offset = readOffset();
    DartType typeArgument = readDartType();
    return new SetConcatenation(readExpressionList(),
        typeArgument: typeArgument)
      ..fileOffset = offset;
  }

  Expression _readMapConcatenation() {
    int offset = readOffset();
    DartType keyType = readDartType();
    DartType valueType = readDartType();
    return new MapConcatenation(readExpressionList(),
        keyType: keyType, valueType: valueType)
      ..fileOffset = offset;
  }

  Expression _readInstanceCreation() {
    int offset = readOffset();
    Reference classReference = readNonNullClassReference();
    List<DartType> typeArguments = readDartTypeList();
    int fieldValueCount = readUInt30();
    Map<Reference, Expression> fieldValues = <Reference, Expression>{};
    for (int i = 0; i < fieldValueCount; i++) {
      final Reference fieldRef = readNonNullCanonicalNameReference().reference;
      final Expression value = readExpression();
      fieldValues[fieldRef] = value;
    }
    int assertCount = readUInt30();
    List<AssertStatement> asserts;

    if (!useGrowableLists && assertCount == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      asserts = emptyListOfAssertStatement;
    } else {
      asserts = new List<AssertStatement>.generate(
          assertCount, (_) => readStatement() as AssertStatement,
          growable: false);
    }
    List<Expression> unusedArguments = readExpressionList();
    return new InstanceCreation(
        classReference, typeArguments, fieldValues, asserts, unusedArguments)
      ..fileOffset = offset;
  }

  Expression _readFileUriExpression() {
    Uri fileUri = readUriReference();
    int offset = readOffset();
    return new FileUriExpression(readExpression(), fileUri)
      ..fileOffset = offset;
  }

  Expression _readIsExpression() {
    int offset = readOffset();
    return new IsExpression(readExpression(), readDartType())
      ..fileOffset = offset;
  }

  Expression _readAsExpression() {
    int offset = readOffset();
    int flags = readByte();
    return new AsExpression(readExpression(), readDartType())
      ..fileOffset = offset
      ..flags = flags;
  }

  Expression _readStringLiteral() {
    int offset = readOffset();
    return new StringLiteral(readStringReference())..fileOffset = offset;
  }

  Expression _readSpecializedIntLiteral(int tagByte) {
    int biasedValue = tagByte & Tag.SpecializedPayloadMask;
    return new IntLiteral(biasedValue - Tag.SpecializedIntLiteralBias)
      ..fileOffset = readOffset();
  }

  Expression _readPositiveIntLiteral() {
    int offset = readOffset();
    int value = readUInt30();
    return new IntLiteral(value)..fileOffset = offset;
  }

  Expression _readNegativeIntLiteral() {
    int offset = readOffset();
    int value = -readUInt30();
    return new IntLiteral(value)..fileOffset = offset;
  }

  Expression _readBigIntLiteral() {
    int offset = readOffset();
    int value = int.parse(readStringReference());
    return new IntLiteral(value)..fileOffset = offset;
  }

  Expression _readDoubleLiteral() {
    int offset = readOffset();
    double value = readDouble();
    return new DoubleLiteral(value)..fileOffset = offset;
  }

  Expression _readTrueLiteral() {
    return new BoolLiteral(true)..fileOffset = readOffset();
  }

  Expression _readFalseLiteral() {
    return new BoolLiteral(false)..fileOffset = readOffset();
  }

  Expression _readNullLiteral() {
    return new NullLiteral()..fileOffset = readOffset();
  }

  Expression _readSymbolLiteral() {
    int offset = readOffset();
    String value = readStringReference();
    return new SymbolLiteral(value)..fileOffset = offset;
  }

  Expression _readTypeLiteral() {
    int offset = readOffset();
    return new TypeLiteral(readDartType())..fileOffset = offset;
  }

  Expression _readThisLiteral() {
    return new ThisExpression()..fileOffset = readOffset();
  }

  Expression _readRethrow() {
    int offset = readOffset();
    return new Rethrow()..fileOffset = offset;
  }

  Expression _readThrow() {
    int offset = readOffset();
    int flags = readByte();
    return new Throw(readExpression())
      ..fileOffset = offset
      ..flags = flags;
  }

  Expression _readListLiteral() {
    int offset = readOffset();
    DartType typeArgument = readDartType();
    return new ListLiteral(readExpressionList(),
        typeArgument: typeArgument, isConst: false)
      ..fileOffset = offset;
  }

  Expression _readConstListLiteral() {
    int offset = readOffset();
    DartType typeArgument = readDartType();
    return new ListLiteral(readExpressionList(),
        typeArgument: typeArgument, isConst: true)
      ..fileOffset = offset;
  }

  Expression _readSetLiteral() {
    int offset = readOffset();
    DartType typeArgument = readDartType();
    return new SetLiteral(readExpressionList(),
        typeArgument: typeArgument, isConst: false)
      ..fileOffset = offset;
  }

  Expression _readConstSetLiteral() {
    int offset = readOffset();
    DartType typeArgument = readDartType();
    return new SetLiteral(readExpressionList(),
        typeArgument: typeArgument, isConst: true)
      ..fileOffset = offset;
  }

  Expression _readMapLiteral() {
    int offset = readOffset();
    DartType keyType = readDartType();
    DartType valueType = readDartType();
    return new MapLiteral(readMapLiteralEntryList(),
        keyType: keyType, valueType: valueType, isConst: false)
      ..fileOffset = offset;
  }

  Expression _readConstMapLiteral() {
    int offset = readOffset();
    DartType keyType = readDartType();
    DartType valueType = readDartType();
    return new MapLiteral(readMapLiteralEntryList(),
        keyType: keyType, valueType: valueType, isConst: true)
      ..fileOffset = offset;
  }

  Expression _readRecordLiteral() {
    int offset = readOffset();
    List<Expression> positional = readExpressionList();
    List<NamedExpression> named = readNamedExpressionList();
    RecordType recordType = readDartType() as RecordType;
    return new RecordLiteral(positional, named, recordType, isConst: false)
      ..fileOffset = offset;
  }

  Expression _readConstRecordLiteral() {
    int offset = readOffset();
    List<Expression> positional = readExpressionList();
    List<NamedExpression> named = readNamedExpressionList();
    RecordType recordType = readDartType() as RecordType;
    return new RecordLiteral(positional, named, recordType, isConst: true)
      ..fileOffset = offset;
  }

  Expression _readAwaitExpression() {
    int offset = readOffset();
    return new AwaitExpression(readExpression())
      ..fileOffset = offset
      ..runtimeCheckType = readDartTypeOption();
  }

  Expression _readFunctionExpression() {
    int offset = readOffset();
    return new FunctionExpression(readFunctionNode())..fileOffset = offset;
  }

  Expression _readLet() {
    int offset = readOffset();
    VariableDeclaration variable = readVariableDeclaration();
    int stackHeight = variableStack.length;
    pushVariableDeclaration(variable);
    Expression body = readExpression();
    variableStack.length = stackHeight;
    return new Let(variable, body)..fileOffset = offset;
  }

  Expression _readBlockExpression() {
    int offset = readOffset();
    int stackHeight = variableStack.length;
    List<Statement> statements = readStatementListAlwaysGrowable();
    Expression value = readExpression();
    variableStack.length = stackHeight;
    return new BlockExpression(new Block(statements), value)
      ..fileOffset = offset;
  }

  Expression _readInstantiation() {
    int offset = readOffset();
    Expression expression = readExpression();
    List<DartType> typeArguments = readDartTypeList();
    return new Instantiation(expression, typeArguments)..fileOffset = offset;
  }

  Expression _readConstantExpression() {
    int offset = readOffset();
    DartType type = readDartType();
    Constant constant = readConstantReference();
    return new ConstantExpression(constant, type)..fileOffset = offset;
  }

  Expression _readFileUriConstantExpression() {
    int offset = readOffset();
    Uri fileUri = readUriReference();
    DartType type = readDartType();
    Constant constant = readConstantReference();
    return new FileUriConstantExpression(constant, type: type, fileUri: fileUri)
      ..fileOffset = offset;
  }

  List<MapLiteralEntry> readMapLiteralEntryList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfMapLiteralEntry;
    }
    return new List<MapLiteralEntry>.generate(length, (_) => readMapEntry(),
        growable: useGrowableLists);
  }

  MapLiteralEntry readMapEntry() {
    return new MapLiteralEntry(readExpression(), readExpression());
  }

  Pattern _readPattern() {
    int tag = readByte();
    switch (tag) {
      case Tag.AndPattern:
        return _readAndPattern();
      case Tag.AssignedVariablePattern:
        return _readAssignedVariablePattern();
      case Tag.CastPattern:
        return _readCastPattern();
      case Tag.ConstantPattern:
        return _readConstantPattern();
      case Tag.InvalidPattern:
        return _readInvalidPattern();
      case Tag.ListPattern:
        return _readListPattern();
      case Tag.MapPattern:
        return _readMapPattern();
      case Tag.NamedPattern:
        return _readNamedPattern();
      case Tag.NullAssertPattern:
        return _readNullAssertPattern();
      case Tag.NullCheckPattern:
        return _readNullCheckPattern();
      case Tag.ObjectPattern:
        return _readObjectPattern();
      case Tag.OrPattern:
        return _readOrPattern();
      case Tag.RecordPattern:
        return _readRecordPattern();
      case Tag.RelationalPattern:
        return _readRelationalPattern();
      case Tag.RestPattern:
        return _readRestPattern();
      case Tag.VariablePattern:
        return _readVariablePattern();
      case Tag.WildcardPattern:
        return _readWildcardPattern();
      default:
        throw fail('unexpected pattern tag: $tag');
    }
  }

  Pattern? _readOptionalPattern() {
    return readAndCheckOptionTag() ? _readPattern() : null;
  }

  List<Pattern> _readPatternList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfPattern;
    }
    return new List<Pattern>.generate(length, (_) => _readPattern(),
        growable: useGrowableLists);
  }

  List<NamedPattern> _readNamedPatternList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfNamedPattern;
    }
    return new List<NamedPattern>.generate(
        length, (_) => _readPattern() as NamedPattern,
        growable: useGrowableLists);
  }

  List<VariableDeclaration> _readVariableReferenceList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfVariableDeclaration;
    }
    return new List<VariableDeclaration>.generate(
        length, (_) => readVariableReference(),
        growable: useGrowableLists);
  }

  List<MapPatternEntry> _readMapPatternEntryList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfMapPatternEntry;
    }
    return new List<MapPatternEntry>.generate(
        length, (_) => _readMapPatternEntry(),
        growable: useGrowableLists);
  }

  AndPattern _readAndPattern() {
    int fileOffset = readOffset();
    return new AndPattern(_readPattern(), _readPattern())
      ..fileOffset = fileOffset;
  }

  AssignedVariablePattern _readAssignedVariablePattern() {
    int fileOffset = readOffset();
    VariableDeclaration variable = readVariableReference();
    DartType? matchedType = readDartTypeOption();
    bool needsCheck = readByte() == 1;
    return AssignedVariablePattern(variable)
      ..fileOffset = fileOffset
      ..matchedValueType = matchedType
      ..needsCast = needsCheck;
  }

  CastPattern _readCastPattern() {
    int fileOffset = readOffset();
    return new CastPattern(_readPattern(), readDartType())
      ..fileOffset = fileOffset;
  }

  ConstantPattern _readConstantPattern() {
    int fileOffset = readOffset();
    Expression expression = readExpression();
    DartType? expressionType = readDartTypeOption();
    Reference? equalsTargetReference = readNullableMemberReference();
    FunctionType? equalsType = readDartTypeOption() as FunctionType?;
    return new ConstantPattern(expression)
      ..expressionType = expressionType
      ..equalsTargetReference = equalsTargetReference
      ..equalsType = equalsType
      ..fileOffset = fileOffset;
  }

  InvalidPattern _readInvalidPattern() {
    int fileOffset = readOffset();
    Expression invalidExpression = readExpression();
    List<VariableDeclaration> declaredVariables =
        readAndPushVariableDeclarationList();
    return InvalidPattern(invalidExpression,
        declaredVariables: declaredVariables)
      ..fileOffset = fileOffset;
  }

  ListPattern _readListPattern() {
    int fileOffset = readOffset();
    DartType? typeArgument = readDartTypeOption();
    List<Pattern> patterns = _readPatternList();
    DartType? requiredType = readDartTypeOption();
    DartType? matchedValueType = readDartTypeOption();
    int flags = readByte();
    DartType? lookupType = readDartTypeOption();
    Reference? lengthTargetReference = readNullableMemberReference();
    DartType? lengthType = readDartTypeOption();
    Reference? lengthCheckTargetReference = readNullableMemberReference();
    FunctionType? lengthCheckType = readDartTypeOption() as FunctionType?;
    Reference? sublistTargetReference = readNullableMemberReference();
    FunctionType? sublistType = readDartTypeOption() as FunctionType?;
    Reference? minusTargetReference = readNullableMemberReference();
    FunctionType? minusType = readDartTypeOption() as FunctionType?;
    Reference? indexGetTargetReference = readNullableMemberReference();
    FunctionType? indexGetType = readDartTypeOption() as FunctionType?;
    return new ListPattern(typeArgument, patterns)
      ..requiredType = requiredType
      ..matchedValueType = matchedValueType
      ..flags = flags
      ..lookupType = lookupType
      ..lengthTargetReference = lengthTargetReference
      ..lengthType = lengthType
      ..lengthCheckTargetReference = lengthCheckTargetReference
      ..lengthCheckType = lengthCheckType
      ..sublistTargetReference = sublistTargetReference
      ..sublistType = sublistType
      ..minusTargetReference = minusTargetReference
      ..minusType = minusType
      ..indexGetTargetReference = indexGetTargetReference
      ..indexGetType = indexGetType
      ..fileOffset = fileOffset;
  }

  MapPattern _readMapPattern() {
    int fileOffset = readOffset();
    DartType? keyType = readDartTypeOption();
    DartType? valueType = readDartTypeOption();
    List<MapPatternEntry> entries = _readMapPatternEntryList();
    DartType? requiredType = readDartTypeOption();
    DartType? matchedValueType = readDartTypeOption();
    int flags = readByte();
    DartType? lookupType = readDartTypeOption();
    Reference? containsKeyTargetReference = readNullableMemberReference();
    FunctionType? containsKeyType = readDartTypeOption() as FunctionType?;
    Reference? indexGetTargetReference = readNullableMemberReference();
    FunctionType? indexGetType = readDartTypeOption() as FunctionType?;
    return new MapPattern(keyType, valueType, entries)
      ..requiredType = requiredType
      ..matchedValueType = matchedValueType
      ..flags = flags
      ..lookupType = lookupType
      ..containsKeyTargetReference = containsKeyTargetReference
      ..containsKeyType = containsKeyType
      ..indexGetTargetReference = indexGetTargetReference
      ..indexGetType = indexGetType
      ..fileOffset = fileOffset;
  }

  NamedPattern _readNamedPattern() {
    int fileOffset = readOffset();
    String name = readStringReference();
    Pattern pattern = _readPattern();
    Name fieldName = readName();
    ObjectAccessKind accessKind = ObjectAccessKind.values[readByte()];
    Reference? targetReference = readNullableMemberReference();
    DartType? resultType = readDartTypeOption();
    RecordType? recordType = readDartTypeOption() as RecordType?;
    int recordFieldIndex = readUInt30();
    FunctionType? functionType = readDartTypeOption() as FunctionType?;
    List<DartType>? typeArguments;
    if (readAndCheckOptionTag()) {
      typeArguments = readDartTypeList();
    }
    return new NamedPattern(name, pattern)
      ..fieldName = fieldName
      ..accessKind = accessKind
      ..targetReference = targetReference
      ..resultType = resultType
      ..recordType = recordType
      ..recordFieldIndex = recordFieldIndex
      ..functionType = functionType
      ..typeArguments = typeArguments
      ..fileOffset = fileOffset;
  }

  NullAssertPattern _readNullAssertPattern() {
    int fileOffset = readOffset();
    Pattern pattern = _readPattern();
    return new NullAssertPattern(pattern)..fileOffset = fileOffset;
  }

  NullCheckPattern _readNullCheckPattern() {
    int fileOffset = readOffset();
    Pattern pattern = _readPattern();
    return new NullCheckPattern(pattern)..fileOffset = fileOffset;
  }

  ObjectPattern _readObjectPattern() {
    int fileOffset = readOffset();
    DartType type = readDartType();
    List<NamedPattern> fields = _readNamedPatternList();
    DartType? matchedType = readDartTypeOption();
    bool needsCheck = readByte() == 1;
    DartType? objectType = readDartTypeOption();
    return new ObjectPattern(type, fields)
      ..matchedValueType = matchedType
      ..needsCheck = needsCheck
      ..lookupType = objectType
      ..fileOffset = fileOffset;
  }

  OrPattern _readOrPattern() {
    int fileOffset = readOffset();
    Pattern left = _readPattern();
    Pattern right = _readPattern();
    List<VariableDeclaration> orPatternJointVariables =
        _readVariableReferenceList();
    return new OrPattern(left, right,
        orPatternJointVariables: orPatternJointVariables)
      ..fileOffset = fileOffset;
  }

  RecordPattern _readRecordPattern() {
    int fileOffset = readOffset();
    List<Pattern> patterns = _readPatternList();
    RecordType? type = readDartTypeOption() as RecordType?;
    DartType? matchedType = readDartTypeOption();
    bool needsCheck = readByte() == 1;
    RecordType? recordType = readDartTypeOption() as RecordType?;
    return new RecordPattern(patterns)
      ..requiredType = type
      ..matchedValueType = matchedType
      ..needsCheck = needsCheck
      ..lookupType = recordType
      ..fileOffset = fileOffset;
  }

  RelationalPattern _readRelationalPattern() {
    int fileOffset = readOffset();
    RelationalPatternKind kind = RelationalPatternKind.values[readByte()];
    Expression expression = readExpression();
    DartType? expressionType = readDartTypeOption();
    DartType? matchedType = readDartTypeOption();
    RelationalAccessKind accessKind = RelationalAccessKind.values[readByte()];
    Name name = readName();
    Reference? targetReference = readNullableMemberReference();
    List<DartType>? typeArguments;
    if (readAndCheckOptionTag()) {
      typeArguments = readDartTypeList();
    }
    FunctionType? functionType = readDartTypeOption() as FunctionType?;
    return new RelationalPattern(kind, expression)
      ..expressionType = expressionType
      ..matchedValueType = matchedType
      ..accessKind = accessKind
      ..name = name
      ..targetReference = targetReference
      ..typeArguments = typeArguments
      ..functionType = functionType
      ..fileOffset = fileOffset;
  }

  RestPattern _readRestPattern() {
    int fileOffset = readOffset();
    Pattern? subPattern = _readOptionalPattern();
    return new RestPattern(subPattern)..fileOffset = fileOffset;
  }

  VariablePattern _readVariablePattern() {
    int fileOffset = readOffset();
    DartType? type = readDartTypeOption();
    VariableDeclaration variable = readVariableDeclaration();
    DartType? matchedType = readDartTypeOption();
    return new VariablePattern(type, variable)
      ..matchedValueType = matchedType
      ..fileOffset = fileOffset;
  }

  WildcardPattern _readWildcardPattern() {
    int fileOffset = readOffset();
    DartType? type = readDartTypeOption();
    return new WildcardPattern(type)..fileOffset = fileOffset;
  }

  MapPatternEntry _readMapPatternEntry() {
    int tag = readByte();
    switch (tag) {
      case Tag.MapPatternEntry:
        int fileOffset = readOffset();
        Expression key = readExpression();
        Pattern value = _readPattern();
        DartType? keyType = readDartTypeOption();
        return new MapPatternEntry(key, value)
          ..keyType = keyType
          ..fileOffset = fileOffset;
      case Tag.MapPatternRestEntry:
        int fileOffset = readOffset();
        return new MapPatternRestEntry()..fileOffset = fileOffset;
      default:
        throw fail('unexpected pattern tag: $tag');
    }
  }

  SwitchExpression _readSwitchExpression() {
    int fileOffset = readOffset();
    Expression expression = readExpression();
    DartType? expressionType = readDartTypeOption();
    List<SwitchExpressionCase> cases = _readSwitchExpressionCaseList();
    DartType? staticType = readDartTypeOption();
    return new SwitchExpression(expression, cases)
      ..expressionType = expressionType
      ..staticType = staticType
      ..fileOffset = fileOffset;
  }

  List<SwitchExpressionCase> _readSwitchExpressionCaseList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfSwitchExpressionCase;
    }
    return new List<SwitchExpressionCase>.generate(
        length, (_) => _readSwitchExpressionCase(),
        growable: useGrowableLists);
  }

  SwitchExpressionCase _readSwitchExpressionCase() {
    int fileOffset = readOffset();
    PatternGuard patternGuard = _readPatternGuard();
    Expression expression = readExpression();
    return new SwitchExpressionCase(patternGuard, expression)
      ..fileOffset = fileOffset;
  }

  PatternGuard _readPatternGuard() {
    int fileOffset = readOffset();
    Pattern pattern = _readPattern();
    Expression? guard = readExpressionOption();
    return new PatternGuard(pattern, guard)..fileOffset = fileOffset;
  }

  IfCaseStatement _readIfCaseStatement() {
    int fileOffset = readOffset();
    Expression expression = readExpression();
    PatternGuard patternGuard = _readPatternGuard();
    Statement then = readStatement();
    Statement? otherwise = readStatementOption();
    DartType? matchedValueType = readDartTypeOption();
    return new IfCaseStatement(expression, patternGuard, then, otherwise)
      ..matchedValueType = matchedValueType
      ..fileOffset = fileOffset;
  }

  PatternAssignment _readPatternAssignment() {
    int fileOffset = readOffset();
    Pattern pattern = _readPattern();
    Expression expression = readExpression();
    DartType? matchedValueType = readDartTypeOption();
    return new PatternAssignment(pattern, expression)
      ..matchedValueType = matchedValueType
      ..fileOffset = fileOffset;
  }

  PatternVariableDeclaration _readPatternVariableDeclaration() {
    int fileOffset = readOffset();
    Pattern pattern = _readPattern();
    Expression expression = readExpression();
    bool isFinal = readByte() == 1;
    DartType? matchedValueType = readDartTypeOption();
    return new PatternVariableDeclaration(pattern, expression, isFinal: isFinal)
      ..matchedValueType = matchedValueType
      ..fileOffset = fileOffset;
  }

  PatternSwitchStatement _readPatternSwitchStatement() {
    int fileOffset = readOffset();
    Expression expression = readExpression();
    DartType? expressionType = readDartTypeOption();
    int count = readUInt30();
    List<PatternSwitchCase> cases;
    if (!useGrowableLists && count == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      cases = emptyListOfPatternSwitchCase;
    } else {
      cases = new List<PatternSwitchCase>.generate(
          count,
          (_) => new PatternSwitchCase([], [], dummyStatement,
              isDefault: false,
              hasLabel: false,
              jointVariables: [],
              jointVariableFirstUseOffsets: null),
          growable: useGrowableLists);
    }
    switchCaseStack.addAll(cases);
    for (int i = 0; i < cases.length; ++i) {
      _readPatternSwitchCaseInto(cases[i]);
    }
    switchCaseStack.length -= count;
    return new PatternSwitchStatement(expression, cases)
      ..expressionTypeInternal = expressionType
      ..fileOffset = fileOffset;
  }

  void _readPatternSwitchCaseInto(PatternSwitchCase caseNode) {
    int variableCount = readUInt30();
    for (int i = 0; i < variableCount; ++i) {
      caseNode.jointVariables.add(readVariableDeclaration()..parent = caseNode);
    }
    int caseCount = readUInt30();
    for (int i = 0; i < caseCount; ++i) {
      caseNode.caseOffsets.add(readOffset());
      caseNode.patternGuards.add(_readPatternGuard()..parent = caseNode);
    }
    int flags = readByte();
    caseNode.isDefault = (flags & 0x1) != 0;
    caseNode.hasLabel = (flags & 0x2) != 0;
    caseNode.body = readStatement()..parent = caseNode;
  }

  List<Statement> readStatementListAlwaysGrowable() {
    int length = readUInt30();
    return new List<Statement>.generate(length, (_) => readStatement(),
        growable: true);
  }

  Statement? readStatementOrNullIfEmpty() {
    Statement node = readStatement();
    if (node is EmptyStatement) {
      return null;
    } else {
      return node;
    }
  }

  Statement? readStatementOption() {
    return readAndCheckOptionTag() ? readStatement() : null;
  }

  Statement readStatement() {
    int tag = readByte();
    switch (tag) {
      // 23.90% (14.98% - 41.04%).
      case Tag.ReturnStatement:
        return _readReturnStatement();

      // 22.74% (15.27% - 32.36%).
      case Tag.ExpressionStatement:
        return _readExpressionStatement();

      // 21.29% (17.70% - 25.00%).
      case Tag.Block:
        return _readBlock();

      // 9.62% (6.92% - 12.64%).
      case Tag.VariableDeclaration:
        return _readVariableDeclaration();

      // 9.28% (6.69% - 11.18%).
      case Tag.EmptyStatement:
        return _readEmptyStatement();

      // 9.06% (6.03% - 11.58%).
      case Tag.IfStatement:
        return _readIfStatement();

      // The rest is < 2% on average in sampled dills.
      case Tag.AssertBlock:
        return _readAssertBlock();
      case Tag.AssertStatement:
        return _readAssertStatement();
      case Tag.LabeledStatement:
        return _readLabeledStatement();
      case Tag.BreakStatement:
        return _readBreakStatement();
      case Tag.WhileStatement:
        return _readWhileStatement();
      case Tag.DoStatement:
        return _readDoStatement();
      case Tag.ForStatement:
        return _readForStatement();
      case Tag.ForInStatement:
      case Tag.AsyncForInStatement:
        return _readForInStatement(tag);
      case Tag.SwitchStatement:
        return _readSwitchStatement();
      case Tag.ContinueSwitchStatement:
        return _readContinueSwitchStatement();
      case Tag.TryCatch:
        return _readTryCatch();
      case Tag.TryFinally:
        return _readTryFinally();
      case Tag.YieldStatement:
        return _readYieldStatement();
      case Tag.FunctionDeclaration:
        return _readFunctionDeclaration();
      case Tag.IfCaseStatement:
        return _readIfCaseStatement();
      case Tag.PatternVariableDeclaration:
        return _readPatternVariableDeclaration();
      case Tag.PatternSwitchStatement:
        return _readPatternSwitchStatement();
      default:
        throw fail('unexpected statement tag: $tag');
    }
  }

  Statement _readExpressionStatement() {
    return new ExpressionStatement(readExpression());
  }

  Statement _readEmptyStatement() {
    return new EmptyStatement();
  }

  Statement _readAssertStatement() {
    return new AssertStatement(readExpression(),
        conditionStartOffset: readOffset(),
        conditionEndOffset: readOffset(),
        message: readExpressionOption());
  }

  Statement _readLabeledStatement() {
    LabeledStatement label = new LabeledStatement(null);
    labelStack.add(label);
    int offset = readOffset();
    label.fileOffset = offset;
    label.body = readStatement()..parent = label;
    labelStack.removeLast();
    return label;
  }

  Statement _readBreakStatement() {
    int offset = readOffset();
    int index = readUInt30();
    return new BreakStatement(labelStack[labelStackBase + index])
      ..fileOffset = offset;
  }

  Statement _readWhileStatement() {
    int offset = readOffset();
    return new WhileStatement(readExpression(), readStatement())
      ..fileOffset = offset;
  }

  Statement _readDoStatement() {
    int offset = readOffset();
    return new DoStatement(readStatement(), readExpression())
      ..fileOffset = offset;
  }

  Statement _readForStatement() {
    int variableStackHeight = variableStack.length;
    int offset = readOffset();
    List<VariableDeclaration> variables = readAndPushVariableDeclarationList();
    Expression? condition = readExpressionOption();
    List<Expression> updates = readExpressionList();
    Statement body = readStatement();
    variableStack.length = variableStackHeight;
    return new ForStatement(variables, condition, updates, body)
      ..fileOffset = offset;
  }

  Statement _readForInStatement(int tag) {
    bool isAsync = tag == Tag.AsyncForInStatement;
    int variableStackHeight = variableStack.length;
    int offset = readOffset();
    int bodyOffset = readOffset();
    VariableDeclaration variable = readAndPushVariableDeclaration();
    Expression iterable = readExpression();
    Statement body = readStatement();
    variableStack.length = variableStackHeight;
    return new ForInStatement(variable, iterable, body, isAsync: isAsync)
      ..fileOffset = offset
      ..bodyOffset = bodyOffset;
  }

  Statement _readSwitchStatement() {
    int offset = readOffset();
    bool isExplicitlyExhaustive = readByte() == 1;
    Expression expression = readExpression();
    DartType? expressionType = readDartTypeOption();
    int count = readUInt30();
    List<SwitchCase> cases;
    if (!useGrowableLists && count == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      cases = emptyListOfSwitchCase;
    } else {
      cases = new List<SwitchCase>.generate(
          count,
          (_) => new SwitchCase(<Expression>[], <int>[], dummyStatement,
              isDefault: false),
          growable: useGrowableLists);
    }
    switchCaseStack.addAll(cases);
    for (int i = 0; i < cases.length; ++i) {
      _readSwitchCaseInto(cases[i]);
    }
    switchCaseStack.length -= count;
    return new SwitchStatement(expression, cases,
        isExplicitlyExhaustive: isExplicitlyExhaustive)
      ..expressionTypeInternal = expressionType
      ..fileOffset = offset;
  }

  Statement _readContinueSwitchStatement() {
    int offset = readOffset();
    int index = readUInt30();
    return new ContinueSwitchStatement(
        switchCaseStack[switchCaseStackBase + index])
      ..fileOffset = offset;
  }

  Statement _readIfStatement() {
    int offset = readOffset();
    return new IfStatement(
        readExpression(), readStatement(), readStatementOrNullIfEmpty())
      ..fileOffset = offset;
  }

  Statement _readReturnStatement() {
    int offset = readOffset();
    return new ReturnStatement(readExpressionOption())..fileOffset = offset;
  }

  Statement _readTryCatch() {
    int offset = readOffset();
    Statement body = readStatement();
    int flags = readByte();
    return new TryCatch(body, readCatchList(), isSynthetic: flags & 2 == 2)
      ..fileOffset = offset;
  }

  Statement _readTryFinally() {
    int offset = readOffset();
    return new TryFinally(readStatement(), readStatement())
      ..fileOffset = offset;
  }

  Statement _readYieldStatement() {
    int offset = readOffset();
    int flags = readByte();
    return new YieldStatement(readExpression(),
        isYieldStar: flags & YieldStatement.FlagYieldStar != 0)
      ..fileOffset = offset;
  }

  Statement _readVariableDeclaration() {
    VariableDeclaration variable = readVariableDeclaration();
    variableStack.add(variable); // Will be popped by the enclosing scope.
    return variable;
  }

  Statement _readFunctionDeclaration() {
    int offset = readOffset();
    VariableDeclaration variable = readVariableDeclaration();
    variableStack.add(variable); // Will be popped by the enclosing scope.
    return new FunctionDeclaration(variable, readFunctionNode())
      ..fileOffset = offset;
  }

  void _readSwitchCaseInto(SwitchCase caseNode) {
    int offset = readOffset();
    caseNode.fileOffset = offset;
    int length = readUInt30();
    for (int i = 0; i < length; ++i) {
      caseNode.expressionOffsets.add(readOffset());
      caseNode.expressions.add(readExpression()..parent = caseNode);
    }
    caseNode.isDefault = readByte() == 1;
    caseNode.body = readStatement()..parent = caseNode;
  }

  List<Catch> readCatchList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfCatch;
    }
    return new List<Catch>.generate(length, (_) => readCatch(),
        growable: useGrowableLists);
  }

  Catch readCatch() {
    int variableStackHeight = variableStack.length;
    int offset = readOffset();
    DartType guard = readDartType();
    VariableDeclaration? exception = readAndPushVariableDeclarationOption();
    VariableDeclaration? stackTrace = readAndPushVariableDeclarationOption();
    Statement body = readStatement();
    variableStack.length = variableStackHeight;
    return new Catch(exception, body, guard: guard, stackTrace: stackTrace)
      ..fileOffset = offset;
  }

  Block _readBlock() {
    int stackHeight = variableStack.length;
    int offset = readOffset();
    int endOffset = readOffset();
    List<Statement> body = readStatementListAlwaysGrowable();
    variableStack.length = stackHeight;
    return new Block(body)
      ..fileOffset = offset
      ..fileEndOffset = endOffset;
  }

  AssertBlock _readAssertBlock() {
    int stackHeight = variableStack.length;
    List<Statement> body = readStatementListAlwaysGrowable();
    variableStack.length = stackHeight;
    return new AssertBlock(body);
  }

  Supertype readSupertype() {
    InterfaceType type = readDartType(forSupertype: true) as InterfaceType;
    assert(
        type.nullability == _currentLibrary!.nonNullable,
        "In serialized form supertypes should have Nullability.legacy if they "
        "are in a library that is opted out of the NNBD feature.  If they are "
        "in an opted-in library, they should have Nullability.nonNullable.");
    return new Supertype.byReference(type.classReference, type.typeArguments);
  }

  Supertype? readSupertypeOption() {
    return readAndCheckOptionTag() ? readSupertype() : null;
  }

  List<Supertype> readSupertypeList([List<Supertype>? result]) {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfSupertype;
    }
    if (result != null) {
      for (int i = 0; i < length; ++i) {
        result.add(readSupertype());
      }
      return result;
    } else {
      return new List<Supertype>.generate(length, (_) => readSupertype(),
          growable: useGrowableLists);
    }
  }

  List<DartType> readDartTypeList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfDartType;
    }
    return new List<DartType>.generate(length, (_) => readDartType(),
        growable: useGrowableLists);
  }

  List<NamedType> readNamedTypeList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use a
      // constant one for the empty list.
      return emptyListOfNamedType;
    }
    return new List<NamedType>.generate(length, (_) => readNamedType(),
        growable: useGrowableLists);
  }

  NamedType readNamedType() {
    String name = readStringReference();
    DartType type = readDartType();
    int flags = readByte();
    return new NamedType(name, type,
        isRequired: (flags & NamedType.FlagRequiredNamedType) != 0);
  }

  DartType? readDartTypeOption() {
    return readAndCheckOptionTag() ? readDartType() : null;
  }

  DartType readDartType({bool forSupertype = false}) {
    int tag = readByte();
    switch (tag) {
      // 67.66% (59.53% - 77.94%).
      case Tag.SimpleInterfaceType:
        return _readSimpleInterfaceType(forSupertype);

      // 11.64% (9.11% - 15.49%).
      case Tag.SimpleFunctionType:
        return _readSimpleFunctionType();

      // 7.33% (5.11% - 8.76%).
      case Tag.InterfaceType:
        return _readInterfaceType();

      // 5.84% (4.13% - 8.86%).
      case Tag.VoidType:
        return _readVoidType();

      // 3.64% (1.20% - 7.55%).
      case Tag.TypeParameterType:
        return _readTypeParameterType();

      // 2.75% (1.03% - 4.13%).
      case Tag.DynamicType:
        return _readDynamicType();

      // The rest is < 2% on average in sampled dills.
      case Tag.TypedefType:
        return _readTypedefType();
      case Tag.InvalidType:
        return _readInvalidType();
      case Tag.NeverType:
        return _readNeverType();
      case Tag.NullType:
        return _readNullType();
      case Tag.ExtensionType:
        return _readExtensionType();
      case Tag.FunctionType:
        return _readFunctionType();
      case Tag.IntersectionType:
        return _readIntersectionType();
      case Tag.RecordType:
        return _readRecordType();
      case Tag.FutureOrType:
        return _readFutureOrType();
      default:
        throw fail('unexpected dart type tag: $tag');
    }
  }

  DartType _readTypedefType() {
    int nullabilityIndex = readByte();
    return new TypedefType.byReference(readNonNullTypedefReference(),
        Nullability.values[nullabilityIndex], readDartTypeList());
  }

  DartType _readInvalidType() {
    return const InvalidType();
  }

  DartType _readDynamicType() {
    return const DynamicType();
  }

  DartType _readVoidType() {
    return const VoidType();
  }

  DartType _readNeverType() {
    int nullabilityIndex = readByte();
    return NeverType.fromNullability(Nullability.values[nullabilityIndex]);
  }

  DartType _readNullType() {
    return const NullType();
  }

  DartType _readInterfaceType() {
    int nullabilityIndex = readByte();
    Reference reference = readNonNullClassReference();
    List<DartType> typeArguments = readDartTypeList();
    return new InterfaceType.byReference(
        reference, Nullability.values[nullabilityIndex], typeArguments);
  }

  DartType _readSimpleInterfaceType(bool forSupertype) {
    final int nullabilityIndex = readByte();
    final int classReferenceIndex = readUInt30();
    final CanonicalName? canonicalName =
        getNullableCanonicalNameReferenceFromInt(classReferenceIndex);
    if (canonicalName == null) {
      throw 'Expected a class reference to be valid but was `null`.';
    }

    // Check cache.
    final int cacheIndex =
        (classReferenceIndex - 1) * Nullability.values.length +
            nullabilityIndex;
    final DartType? cached = _cachedSimpleInterfaceTypes[cacheIndex];
    if (cached != null) {
      return cached;
    }

    // Not in cache.
    final Reference classReference = canonicalName.reference;
    final DartType result = new InterfaceType.byReference(classReference,
        Nullability.values[nullabilityIndex], const <DartType>[]);
    _cachedSimpleInterfaceTypes[cacheIndex] = result;
    return result;
  }

  DartType _readFutureOrType() {
    int nullabilityIndex = readByte();
    DartType typeArgument = readDartType();
    return new FutureOrType(typeArgument, Nullability.values[nullabilityIndex]);
  }

  DartType _readExtensionType() {
    int nullabilityIndex = readByte();
    Reference reference = readNonNullExtensionTypeDeclarationReference();
    List<DartType> typeArguments = readDartTypeList();
    readDartType(); // Read type erasure.
    return new ExtensionType.byReference(
        reference, Nullability.values[nullabilityIndex], typeArguments);
  }

  DartType _readFunctionType() {
    int typeParameterStackHeight = typeParameterStack.length;
    int nullabilityIndex = readByte();
    List<StructuralParameter> typeParameters =
        readAndPushStructuralParameterList();
    int requiredParameterCount = readUInt30();
    int totalParameterCount = readUInt30();
    List<DartType> positional = readDartTypeList();
    List<NamedType> named = readNamedTypeList();
    assert(positional.length + named.length == totalParameterCount);
    DartType returnType = readDartType();
    typeParameterStack.length = typeParameterStackHeight;
    return new FunctionType(
        positional, returnType, Nullability.values[nullabilityIndex],
        typeParameters: typeParameters,
        requiredParameterCount: requiredParameterCount,
        namedParameters: named);
  }

  DartType _readSimpleFunctionType() {
    int nullabilityIndex = readByte();
    List<DartType> positional = readDartTypeList();
    DartType returnType = readDartType();
    if (positional.isEmpty && returnType is VoidType) {
      // "FunctionType(void Function())" with different nullabilities.
      assert(
          _voidFunctionFunctionTypesCache.length == Nullability.values.length);
      FunctionType? cached = _voidFunctionFunctionTypesCache[nullabilityIndex];
      if (cached != null) {
        return cached;
      }
      FunctionType result = new FunctionType(
          const [], const VoidType(), Nullability.values[nullabilityIndex]);
      _voidFunctionFunctionTypesCache[nullabilityIndex] = result;
      return result;
    }
    return new FunctionType(
        positional, returnType, Nullability.values[nullabilityIndex]);
  }

  DartType _readTypeParameterType() {
    int declaredNullabilityIndex = readByte();
    int index = readUInt30();
    Object typeParameter = typeParameterStack[index];
    if (typeParameter is TypeParameter) {
      return new TypeParameterType(
          typeParameter, Nullability.values[declaredNullabilityIndex]);
    } else {
      typeParameter as StructuralParameter;
      return new StructuralParameterType(
          typeParameter, Nullability.values[declaredNullabilityIndex]);
    }
  }

  DartType _readIntersectionType() {
    TypeParameterType left = readDartType() as TypeParameterType;
    DartType right = readDartType();
    return new IntersectionType(left, right);
  }

  DartType _readRecordType() {
    int nullabilityIndex = readByte();
    List<DartType> positional = readDartTypeList();
    List<NamedType> named = readNamedTypeList();
    return new RecordType(
        positional, named, Nullability.values[nullabilityIndex]);
  }

  List<TypeParameter> readAndPushTypeParameterList(
      [List<TypeParameter>? list, GenericDeclaration? declaration]) {
    int length = readUInt30();
    if (length == 0) {
      if (list != null) return list;
      if (useGrowableLists) {
        return <TypeParameter>[];
      } else {
        return emptyListOfTypeParameter;
      }
    }
    if (list == null) {
      list = new List<TypeParameter>.generate(length,
          (_) => new TypeParameter(null, null)..declaration = declaration,
          growable: useGrowableLists);
    } else if (list.length != length) {
      for (int i = 0; i < length; ++i) {
        list.add(new TypeParameter(null, null)..declaration = declaration);
      }
    }
    typeParameterStack.addAll(list);
    for (int i = 0; i < list.length; ++i) {
      readTypeParameter(list[i]);
    }
    return list;
  }

  List<StructuralParameter> readAndPushStructuralParameterList(
      [List<StructuralParameter>? list]) {
    int length = readUInt30();
    if (length == 0) {
      if (list != null) return list;
      if (useGrowableLists) {
        return <StructuralParameter>[];
      } else {
        return emptyListOfStructuralParameter;
      }
    }
    if (list == null) {
      list = new List<StructuralParameter>.generate(
          length, (_) => new StructuralParameter(null, null),
          growable: useGrowableLists);
    } else if (list.length != length) {
      for (int i = 0; i < length; ++i) {
        list.add(new StructuralParameter(null, null));
      }
    }
    typeParameterStack.addAll(list);
    for (int i = 0; i < list.length; ++i) {
      readStructuralParameter(list[i]);
    }
    return list;
  }

  void readTypeParameter(TypeParameter node) {
    node.flags = readByte();
    node.annotations = readAnnotationList(node);
    int variance = readByte();
    if (variance == TypeParameter.legacyCovariantSerializationMarker) {
      node.variance = null;
    } else {
      node.variance = new Variance.fromEncoding(variance);
    }
    node.name = readStringOrNullIfEmpty();
    node.bound = readDartType();
    node.defaultType = readDartType();
  }

  void readStructuralParameter(StructuralParameter node) {
    node.flags = readByte();
    // For now, [StructuralParameter] objects are encoded as
    // [TypeParameter] objects, to preserve compatibility with the binary format
    // consumers.
    // TODO(cstefantsova): Eventually remove the annotations from the binary
    // encoding of [StructuralParameter] objects.
    readAnnotationList();
    int variance = readByte();
    if (variance == TypeParameter.legacyCovariantSerializationMarker) {
      node.variance = null;
    } else {
      node.variance = new Variance.fromEncoding(variance);
    }
    node.name = readStringOrNullIfEmpty();
    node.bound = readDartType();
    node.defaultType = readDartType();
  }

  Arguments readArguments() {
    int numArguments = readUInt30();
    List<DartType> typeArguments = readDartTypeList();
    List<Expression> positional = readExpressionList();
    List<NamedExpression> named = readNamedExpressionList();
    assert(numArguments == positional.length + named.length);
    return new Arguments(positional, types: typeArguments, named: named);
  }

  List<NamedExpression> readNamedExpressionList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost-constant one for the empty list.
      return emptyListOfNamedExpression;
    }
    return new List<NamedExpression>.generate(
        length, (_) => readNamedExpression(),
        growable: useGrowableLists);
  }

  NamedExpression readNamedExpression() {
    return new NamedExpression(readStringReference(), readExpression());
  }

  List<VariableDeclaration> readAndPushVariableDeclarationList() {
    int length = readUInt30();
    if (!useGrowableLists && length == 0) {
      // When lists don't have to be growable anyway, we might as well use an
      // almost constant one for the empty list.
      return emptyListOfVariableDeclaration;
    }
    return new List<VariableDeclaration>.generate(
        length, (_) => readAndPushVariableDeclaration(),
        growable: useGrowableLists);
  }

  VariableDeclaration? readAndPushVariableDeclarationOption() {
    return readAndCheckOptionTag() ? readAndPushVariableDeclaration() : null;
  }

  VariableDeclaration readAndPushVariableDeclaration() {
    VariableDeclaration variable = readVariableDeclaration();
    variableStack.add(variable);
    return variable;
  }

  VariableDeclaration readVariableDeclaration() {
    int offset = readOffset();
    int fileEqualsOffset = readOffset();
    // The [VariableDeclaration] instance is not created at this point yet,
    // so `null` is temporarily set as the parent of the annotation nodes.
    List<Expression> annotations = readAnnotationList(null);
    int flags = readUInt30();
    VariableDeclaration node = new VariableDeclaration(
        readStringOrNullIfEmpty(),
        type: readDartType(),
        initializer: readExpressionOption(),
        flags: flags)
      ..fileOffset = offset
      ..fileEqualsOffset = fileEqualsOffset;
    if (annotations.isNotEmpty) {
      for (int i = 0; i < annotations.length; ++i) {
        Expression annotation = annotations[i];
        annotation.parent = node;
      }
      node.annotations = annotations;
    }
    return node;
  }

  int readOffset() {
    // Offset is saved as unsigned,
    // but actually ranges from -1 and up (thus the -1)
    return readUInt30() - 1;
  }
}

class BinaryBuilderWithMetadata extends BinaryBuilder implements BinarySource {
  /// List of metadata subsections that have corresponding [MetadataRepository]
  /// and are awaiting to be parsed and attached to nodes.
  List<_MetadataSubsection>? _subsections;
  List<int>? _allKnownMetadataKeys;
  int? _previousMetadataLookupKey;

  BinaryBuilderWithMetadata(Uint8List bytes,
      {String? filename,
      bool disableLazyReading = false,
      bool disableLazyClassReading = false,
      bool? alwaysCreateNewNamedNodes})
      : super(bytes,
            filename: filename,
            disableLazyReading: disableLazyReading,
            disableLazyClassReading: disableLazyClassReading,
            alwaysCreateNewNamedNodes: alwaysCreateNewNamedNodes);

  @override
  void _readMetadataMappings(
      Component component, int binaryOffsetForMetadataPayloads) {
    // If reading a component with several sub-components there's no reason to
    // lookup in old ones.
    _subsections = null;
    _allKnownMetadataKeys = null;

    // At the beginning of this function _byteOffset points right past
    // metadataMappings to string table.

    // Read the length of metadataMappings.
    _byteOffset -= 4;
    final int subSectionCount = readUint32();

    int endOffset = _byteOffset - 4; // End offset of the current subsection.
    for (int i = 0; i < subSectionCount; i++) {
      // RList<Pair<UInt32, UInt32>> nodeOffsetToMetadataOffset
      _byteOffset = endOffset - 4;
      final int mappingLength = readUint32();
      final int mappingStart = (endOffset - 4) - 4 * 2 * mappingLength;
      _byteOffset = mappingStart - 4;

      // UInt32 tag (fixed size StringReference)
      final String tag = _stringTable[readUint32()];

      final MetadataRepository<dynamic>? repository = component.metadata[tag];
      if (repository != null) {
        // Read nodeOffsetToMetadataOffset mapping.
        final Map<int, int> mapping = <int, int>{};
        _byteOffset = mappingStart;
        List<int> allKnownMetadataKeys = _allKnownMetadataKeys ??= [];
        for (int j = 0; j < mappingLength; j++) {
          final int nodeOffset = _componentStartOffset + readUint32();
          final int metadataOffset =
              binaryOffsetForMetadataPayloads + readUint32();
          mapping[nodeOffset] = metadataOffset;
          allKnownMetadataKeys.add(nodeOffset);
        }

        (_subsections ??= <_MetadataSubsection>[])
            .add(new _MetadataSubsection(repository, mapping));
      }

      // Start of the subsection and the end of the previous one.
      endOffset = mappingStart - 4;
    }
    _allKnownMetadataKeys?.sort();
  }

  Object _readMetadata(Node node, MetadataRepository repository, int offset) {
    final int savedOffset = _byteOffset;
    _byteOffset = offset;

    final Object metadata = repository.readFromBinary(node, this);

    _byteOffset = savedOffset;
    return metadata;
  }

  bool _hasMetadata(int nodeOffset) {
    List<int>? allKnownMetadataKeys = _allKnownMetadataKeys;
    if (allKnownMetadataKeys == null) return false;
    if (allKnownMetadataKeys.isEmpty) return false;

    int? prevIndex = _previousMetadataLookupKey;
    if (prevIndex != null) {
      if (prevIndex >= 0 && prevIndex < allKnownMetadataKeys.length - 1) {
        int prevOffset = allKnownMetadataKeys[prevIndex];
        int nextOffset = allKnownMetadataKeys[prevIndex + 1];
        if (prevOffset < nodeOffset && nextOffset > nodeOffset) {
          // Common case: This is between the previously found metadata
          // and the next metadata (and doesn't itself have metadata).
          return false;
        }
      }
    }

    _previousMetadataLookupKey = null;
    int low = 0, high = allKnownMetadataKeys.length - 1;
    while (low < high) {
      int mid = high - ((high - low) >> 1); // Get middle, rounding up.
      int pivot = allKnownMetadataKeys[mid];
      if (pivot <= nodeOffset) {
        low = mid;
      } else {
        high = mid - 1;
      }
    }
    this._previousMetadataLookupKey = low;
    if (allKnownMetadataKeys[low] == nodeOffset) {
      return true;
    }
    return false;
  }

  @override
  T _associateMetadata<T extends Node>(T node, int nodeOffset) {
    if (_subsections == null) {
      return node;
    }
    for (_MetadataSubsection subsection in _subsections!) {
      // First check if there is any metadata associated with this node.
      final int? metadataOffset = subsection.mapping[nodeOffset];
      if (metadataOffset != null) {
        subsection.repository.mapping[node] =
            _readMetadata(node, subsection.repository, metadataOffset);
      }
    }

    return node;
  }

  @override
  DartType readDartType({bool forSupertype = false}) {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final DartType result = super.readDartType(forSupertype: forSupertype);
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  Library readLibrary(Component component, int endOffset) {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final Library result = super.readLibrary(component, endOffset);
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  Typedef readTypedef() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final Typedef result = super.readTypedef();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  Class readClass(int endOffset) {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final Class result = super.readClass(endOffset);
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  Extension readExtension() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final Extension result = super.readExtension();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  ExtensionTypeDeclaration readExtensionTypeDeclaration() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final ExtensionTypeDeclaration result =
        super.readExtensionTypeDeclaration();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  Field readField() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final Field result = super.readField();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  Constructor readConstructor() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final Constructor result = super.readConstructor();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  Procedure readProcedure(int endOffset) {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final Procedure result = super.readProcedure(endOffset);
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  Initializer readInitializer() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final Initializer result = super.readInitializer();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  FunctionNode readFunctionNode(
      {bool lazyLoadBody = false, int outerEndOffset = -1}) {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final FunctionNode result = super.readFunctionNode(
        lazyLoadBody: lazyLoadBody, outerEndOffset: outerEndOffset);
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  Expression readExpression() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final Expression result = super.readExpression();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  Arguments readArguments() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final Arguments result = super.readArguments();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  NamedExpression readNamedExpression() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final NamedExpression result = super.readNamedExpression();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  VariableDeclaration readVariableDeclaration() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final VariableDeclaration result = super.readVariableDeclaration();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  Statement readStatement() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final Statement result = super.readStatement();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  Combinator readCombinator() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final Combinator result = super.readCombinator();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  LibraryDependency readLibraryDependency() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final LibraryDependency result = super.readLibraryDependency();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  LibraryPart readLibraryPart() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final LibraryPart result = super.readLibraryPart();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  void _readSwitchCaseInto(SwitchCase caseNode) {
    _associateMetadata(caseNode, _byteOffset);
    super._readSwitchCaseInto(caseNode);
  }

  @override
  void readTypeParameter(TypeParameter param) {
    _associateMetadata(param, _byteOffset);
    super.readTypeParameter(param);
  }

  @override
  Supertype readSupertype() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    InterfaceType type =
        super.readDartType(forSupertype: true) as InterfaceType;
    Supertype result =
        new Supertype.byReference(type.classReference, type.typeArguments);
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }

  @override
  Name readName() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final Name result = super.readName();
    return hasMetadata ? _associateMetadata(result, nodeOffset) : result;
  }
}

/// Deserialized MetadataMapping corresponding to the given metadata repository.
class _MetadataSubsection {
  /// [MetadataRepository] that can read this subsection.
  final MetadataRepository repository;

  /// Deserialized mapping from node offsets to metadata offsets.
  final Map<int, int> mapping;

  _MetadataSubsection(this.repository, this.mapping);
}
