// 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 'tag.dart';

const int $_ = 95;

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

  new(
    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;

  new(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;

  new(this.version);

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

class CompilationModeError {
  final String message;

  new(this.message);

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

class _ComponentIndex {
  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;

  new({
    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;

  new(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<Variable> variableStack = <Variable>[];
  final List<LabeledStatement> labelStack = <LabeledStatement>[];
  int labelStackBase = 0;
  int switchCaseStackBase = 0;
  final List<SwitchCase> switchCaseStack = <SwitchCase>[];
  final List</* TypeParameter | StructuralParameter */ Object>
  typeParameterStack = <Object>[];
  final List<VariableContext> variableContextStack = <VariableContext>[];
  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];
  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.
  new(
    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 DartTypeList 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 DartTypeList types = readDartTypeList();
    return new InstantiationConstant(tearOffConstant, types);
  }

  Constant _readTypedefTearOffConstant() {
    final StructuralParameterList parameters =
        readAndPushStructuralParameterList();
    final TearOffConstant tearOffConstant =
        readConstantReference() as TearOffConstant;
    final DartTypeList 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 -= numberOfFixedFields(libraryCount) * 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();
    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);

    _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.

    // TODO(alexmarkov): reverse metadata mappings and read forwards
    // Ensure constant table is loaded before metadata is read as it may contain
    // references to the constant table.
    _byteOffset = index.binaryOffsetForStringTable; // Read backwards.
    _readMetadataMappings(component, index.binaryOffsetForMetadataPayloads);

    _associateMetadata(component, _componentStartOffset);

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

  int readScopeSizeAndAllocateContexts() {
    int scopeSize = readUInt30();
    for (int index = 0; index < scopeSize; index++) {
      variableContextStack.add(
        new VariableContext(
          captureKind: CaptureKind.notCaptured,
          // The list of variables will be updated later, in
          // [_readVariableContext].
          variables: const [],
        ),
      );
    }
    return scopeSize;
  }

  Scope? readOptionalScope(int scopeSize) {
    return readAndCheckOptionTag() ? _readScope(scopeSize) : null;
  }

  Scope _readScope(int scopeSize) {
    int contextCount = readUInt30();
    assert(scopeSize == contextCount);
    List<VariableContext> contexts = new List<VariableContext>.generate(
      contextCount,
      (int variableContextIndex) =>
          _readVariableContext(variableContextIndex, scopeSize),
      growable: useGrowableLists,
    );
    variableContextStack.length -= scopeSize;
    return new Scope(contexts: contexts);
  }

  VariableContext _readVariableContext(
    int variableContextIndex,
    int scopeSize,
  ) {
    int captureKindIndex = readByte();
    CaptureKind captureKind = CaptureKind.values[captureKindIndex];
    int variableCount = readUInt30();
    List<VariableBase> variables = new List<VariableBase>.generate(
      variableCount,
      (_) => readVariableReference(),
      growable: useGrowableLists,
    );
    VariableContext variableContext =
        variableContextStack[variableContextStack.length -
            scopeSize +
            variableContextIndex];
    variableContext.captureKind = captureKind;
    variableContext.variables = variables;
    return variableContext;
  }

  /// 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();
    Uri fileUri = readUriReference();
    return new LibraryPart(annotations, partUri, fileUri);
  }

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

  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,
        );
      }
    }
    int scopeSize = readScopeSizeAndAllocateContexts();
    List<Expression> annotations = readAnnotationList(node);
    assert(() {
      debugPath.add(name.text);
      return true;
    }());
    DartType type = readDartType();
    // TODO(63493): Remove the next line when the scopes are serialized before
    // function bodies.
    ThisVariable? thisVariable = readAndPushVariableOption() as ThisVariable?;
    Expression? initializer = readExpressionOption();
    Scope? scope = readOptionalScope(scopeSize);
    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.thisVariable = thisVariable;
    node.thisVariable?.parent = node;
    node.initializer = initializer;
    node.initializer?.parent = node;
    node.scope = scope;
    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;
    }());
    FunctionNodeAndContexts functionNodeAndContexts = readFunctionNode();
    FunctionNode function = functionNodeAndContexts.functionNode;
    if (node == null) {
      node = new Constructor(
        function,
        reference: reference,
        name: name,
        fileUri: fileUri,
      );
    }
    if (function.thisVariable != null) {
      pushVariableDeclaration(function.thisVariable!);
    }
    pushVariableDeclarations(function.positionalParameters);
    pushVariableDeclarations(function.namedParameters);

    int savedVariableContextStackSize = variableContextStack.length;
    if (functionNodeAndContexts.preAllocatedContexts case var contexts?) {
      variableContextStack.addAll(contexts);
    }
    _readInitializers(node);
    variableContextStack.length = savedVariableContextStackSize;

    variableStack.length = 0;
    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;
    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,
    ).functionNode;
    if (node == null) {
      node = new Procedure(
        name,
        kind,
        function,
        reference: reference,
        fileUri: fileUri,
      );
    } else {
      assert(node.kind == kind);
    }
    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.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();
    switch (tag) {
      // 52.71% (43.80% - 59.02%).
      case Tag.FieldInitializer:
        return _readFieldInitializer();

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

      // 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() {
    int offset = readOffset();
    String message = readStringReference();
    int flags = readByte();
    return new InvalidInitializer(message)
      ..flags = flags
      ..fileOffset = offset;
  }

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

  Initializer _readSuperInitializer() {
    int offset = readOffset();
    bool isSynthetic = readByte() == 1;
    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() {
    int offset = readOffset();
    SyntheticVariable variable = readAndPushVariable() as SyntheticVariable;
    // ignore: deprecated_member_use_from_same_package
    return new LocalInitializer(variable, variable.initializer!)
      ..fileOffset = offset;
  }

  Initializer _readAssertInitializer() {
    int offset = readOffset();
    return new AssertInitializer(readStatement() as AssertStatement)
      ..fileOffset = offset;
  }

  FunctionNodeAndContexts 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;
    int scopeSize = readScopeSizeAndAllocateContexts();
    List<VariableContext>? preAllocatedContexts;
    if (scopeSize > 0) {
      preAllocatedContexts = variableContextStack
          .getRange(
            variableContextStack.length - scopeSize,
            variableContextStack.length,
          )
          .toList();
    }
    List<TypeParameter> typeParameters = readAndPushTypeParameterList();
    int variableStackHeight = variableStack.length;
    // TODO(63493): Remove the next line when the scopes are serialized before
    // function bodies.
    ThisVariable? thisVariable = readAndPushVariableOption() as ThisVariable?;
    readUInt30(); // total parameter count.
    int requiredParameterCount = readUInt30();
    List<PositionalParameter> positional = readAndPushPositionalParameterList();
    List<NamedParameter> named = readAndPushNamedParameterList();
    DartType returnType = readDartType();
    DartType? futureValueType = readDartTypeOption();
    RedirectingFactoryTarget? redirectingFactoryTarget;
    if (readAndCheckOptionTag()) {
      Reference? targetReference = readNullableMemberReference();
      DartTypeList? 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;
    Scope? scope;
    List<VariableContext>? capturedContexts;
    if (!lazyLoadBody) {
      labelStackBase = labelStack.length;
      switchCaseStackBase = switchCaseStack.length;
      body = readStatementOption();
      scope = readOptionalScope(scopeSize);
      capturedContexts = readOptionalCapturedContexts();
    }

    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
          ..thisVariable = thisVariable
          ..scope = scope
          ..capturedContexts = capturedContexts;
    thisVariable?.parent = result;

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

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

    return new FunctionNodeAndContexts(result, preAllocatedContexts);
  }

  void _setLazyLoadFunction(
    FunctionNode result,
    int oldLabelStackBase,
    int oldSwitchCaseStackBase,
    int variableStackHeight, {
    required int scopeSize,
  }) {
    final int savedByteOffset = _byteOffset;
    final int componentStartOffset = _componentStartOffset;
    final List<TypeParameter> typeParameters = typeParameterStack
        .cast<TypeParameter>()
        .toList();
    final List<Variable> variables = variableStack.toList();
    final List<VariableContext> variableContexts = variableContextStack
        .toList();
    variableContextStack.length -= scopeSize;
    final Library currentLibrary = _currentLibrary!;
    result.lazyBuilder = () {
      _byteOffset = savedByteOffset;
      _currentLibrary = currentLibrary;
      typeParameterStack.clear();
      typeParameterStack.addAll(typeParameters);
      variableStack.clear();
      variableStack.addAll(variables);
      variableContextStack.clear();
      variableContextStack.addAll(variableContexts);
      _componentStartOffset = componentStartOffset;

      result.body = readStatementOption();
      result.body?.parent = result;
      result.scope = readOptionalScope(scopeSize);
      result.capturedContexts = readOptionalCapturedContexts();
      labelStackBase = oldLabelStackBase;
      switchCaseStackBase = oldSwitchCaseStackBase;
      variableStack.length = variableStackHeight;
      typeParameterStack.clear();
    };
  }

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

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

  Variable? readVariableReferenceOption() {
    return readAndCheckOptionTag() ? readVariableReference() : null;
  }

  DeclaredVariable readDeclaredVariableReference() {
    return readVariableReference() as DeclaredVariable;
  }

  LocalFunctionVariable readLocalFunctionVariableReference() {
    return readVariableReference() as LocalFunctionVariable;
  }

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

  Variable _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();
      case Tag.RedirectingFactoryInvocation:
        return _readRedirectingFactoryInvocation();
      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(readStringReference(), 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();
    return new AbstractSuperPropertyGet.byReference(
      readExpression(),
      readName(),
      readNonNullInstanceMemberReference(),
    )..fileOffset = offset;
  }

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

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

  Expression _readSuperPropertySet() {
    int offset = readOffset();
    return new SuperPropertySet.byReference(
      readExpression(),
      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();
    StructuralParameterList structuralParameters =
        readAndPushStructuralParameterList();
    Expression expression = readExpression();
    DartTypeList 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();
    Expression receiver = readExpression();
    Name name = readName();
    Arguments arguments = readArguments();
    FunctionType functionType = readDartType() as FunctionType;
    DartType resultType = readDartType();
    Reference interfaceTargetReference = readNonNullInstanceMemberReference();
    return new InstanceInvocation.byReference(
        kind,
        receiver,
        name,
        arguments,
        functionType: functionType,
        interfaceTargetReference: interfaceTargetReference,
      )
      ..resultType = resultType
      ..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();
    LocalFunctionVariable variable = readLocalFunctionVariableReference();
    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();
    return new AbstractSuperMethodInvocation.byReference(
      readExpression(),
      readName(),
      readArguments(),
      readNonNullInstanceMemberReference(),
    )..fileOffset = offset;
  }

  Expression _readSuperMethodInvocation() {
    int offset = readOffset();
    return new SuperMethodInvocation.byReference(
      readExpression(),
      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 _readRedirectingFactoryInvocation() {
    int offset = readOffset();
    return new RedirectingFactoryInvocation.byReference(
      readNonNullMemberReference(),
      readExpression() as InvocationExpression,
    )..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();
    DartTypeList 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();
    final LocalFunctionId id = LocalFunctionId(readUInt30());
    return new FunctionExpression(readFunctionNode().functionNode)
      ..fileOffset = offset
      ..id = id;
  }

  Expression _readLet() {
    int offset = readOffset();
    SyntheticVariable variable = readVariable() as SyntheticVariable;
    int stackHeight = variableStack.length;
    pushVariableDeclaration(variable);
    Expression body = readExpression();
    variableStack.length = stackHeight;
    // ignore: deprecated_member_use_from_same_package
    return new Let(variable: variable, value: variable.initializer!, body: body)
      ..fileOffset = offset;
  }

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

  Expression _readInstantiation() {
    int offset = readOffset();
    Expression expression = readExpression();
    DartTypeList 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<DeclaredVariable> _readDeclaredVariableReferenceList() {
    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 emptyListOfDeclaredVariable;
    }
    return new List<DeclaredVariable>.generate(
      length,
      (_) => readDeclaredVariableReference(),
      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();
    String variableName = readStringReference();
    DartType variableType = readDartType();
    Variable writeVariable = readVariableReference();
    DartType matchedValueType = readDartType();
    int flags = readByte();
    return AssignedVariablePattern(
      variableName: variableName,
      variableType: variableType,
      writeVariable: writeVariable,
      matchedValueType: matchedValueType,
      needsCast: flags & AssignedVariablePattern.FlagNeedsCast != 0,
      hasObservableEffect:
          flags & AssignedVariablePattern.FlagHasObservableEffect != 0,
    )..fileOffset = fileOffset;
  }

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

  ConstantPattern _readConstantPattern() {
    int fileOffset = readOffset();
    Expression expression = readExpression();
    DartType expressionType = readDartType();
    Reference equalsTargetReference = readNonNullMemberReference();
    FunctionType equalsType = readDartType() as FunctionType;
    return new ConstantPattern.byReference(
      expression: expression,
      expressionType: expressionType,
      equalsTargetReference: equalsTargetReference,
      equalsType: equalsType,
    )..fileOffset = fileOffset;
  }

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

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

  MapPattern _readMapPattern() {
    int fileOffset = readOffset();
    DartType? keyType = readDartTypeOption();
    DartType? valueType = readDartTypeOption();
    List<MapPatternEntry> entries = _readMapPatternEntryList();
    DartType requiredType = readDartType();
    DartType matchedValueType = readDartType();
    int flags = readByte();
    DartType lookupType = readDartType();
    Reference containsKeyTargetReference = readNonNullMemberReference();
    FunctionType containsKeyType = readDartType() as FunctionType;
    Reference indexGetTargetReference = readNonNullMemberReference();
    FunctionType indexGetType = readDartType() as FunctionType;
    return new MapPattern.byReference(
      keyType: keyType,
      valueType: valueType,
      entries: entries,
      requiredType: requiredType,
      matchedValueType: matchedValueType,
      lookupType: lookupType,
      containsKeyTargetReference: containsKeyTargetReference,
      containsKeyType: containsKeyType,
      indexGetTargetReference: indexGetTargetReference,
      indexGetType: indexGetType,
      flags: flags,
    )..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();
    DartTypeList? typeArguments;
    if (readAndCheckOptionTag()) {
      typeArguments = readDartTypeList();
    }
    return new NamedPattern(name, pattern)
      ..fieldName = fieldName
      ..accessKind = accessKind
      ..targetReference = targetReference
      ..resultType = resultType
      ..recordType = recordType
      ..recordFieldIndex = recordFieldIndex
      ..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 requiredType = readDartType();
    List<NamedPattern> fields = _readNamedPatternList();
    DartType matchedValueType = readDartType();
    bool needsCheck = readByte() == 1;
    return new ObjectPattern(
      requiredType: requiredType,
      fields: fields,
      matchedValueType: matchedValueType,
      needsCheck: needsCheck,
    )..fileOffset = fileOffset;
  }

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

  RecordPattern _readRecordPattern() {
    int fileOffset = readOffset();
    List<Pattern> patterns = _readPatternList();
    RecordType requiredType = readDartType() as RecordType;
    DartType matchedValueType = readDartType();
    bool needsCheck = readByte() == 1;
    RecordType lookupType = readDartType() as RecordType;
    return new RecordPattern(
      patterns: patterns,
      requiredType: requiredType,
      matchedValueType: matchedValueType,
      needsCheck: needsCheck,
      lookupType: lookupType,
    )..fileOffset = fileOffset;
  }

  RelationalPattern _readRelationalPattern() {
    int fileOffset = readOffset();
    RelationalPatternKind kind = RelationalPatternKind.values[readByte()];
    Expression expression = readExpression();
    DartType expressionType = readDartType();
    DartType matchedValueType = readDartType();
    RelationalAccessKind accessKind = RelationalAccessKind.values[readByte()];
    Name name = readName();
    Reference? targetReference = readNullableMemberReference();
    DartTypeList? typeArguments;
    if (readAndCheckOptionTag()) {
      typeArguments = readDartTypeList();
    }
    FunctionType? functionType = readDartTypeOption() as FunctionType?;
    return new RelationalPattern.byReference(
      kind: kind,
      expression: expression,
      expressionType: expressionType,
      matchedValueType: matchedValueType,
      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();
    DeclaredVariable variable = readDeclaredVariable();
    DartType matchedValueType = readDartType();
    return new VariablePattern(
      type: type,
      variable: variable,
      matchedValueType: matchedValueType,
    )..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 = readDartType();
    return new IfCaseStatement(
      expression: expression,
      patternGuard: patternGuard,
      then: then,
      otherwise: otherwise,
      matchedValueType: matchedValueType,
    )..fileOffset = fileOffset;
  }

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

  PatternVariableDeclaration _readPatternVariableDeclaration() {
    int fileOffset = readOffset();
    Pattern pattern = _readPattern();
    Expression expression = readExpression();
    bool isFinal = readByte() == 1;
    DartType matchedValueType = readDartType();
    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,
          jointVariableDeclarations: [],
          jointVariableFirstUseOffsets: null,
          jointVariableScope: 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.jointVariableDeclarations.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.VariableStatement:
        return _readVariableStatement();

      // 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();
    int scopeSize = readScopeSizeAndAllocateContexts();
    Expression condition = readExpression();
    Statement body = readStatement();
    Scope? scope = readOptionalScope(scopeSize);
    return new WhileStatement(condition, body)
      ..fileOffset = offset
      ..scope = scope;
  }

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

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

  Statement _readForInStatement(int tag) {
    bool isAsync = tag == Tag.AsyncForInStatement;
    int variableStackHeight = variableStack.length;
    int offset = readOffset();
    int bodyOffset = readOffset();
    int scopeSize = readScopeSizeAndAllocateContexts();
    DeclaredVariable variable = readAndPushDeclaredVariable();
    Expression iterable = readExpression();
    Statement body = readStatement();
    Scope? scope = readOptionalScope(scopeSize);
    variableStack.length = variableStackHeight;
    return new ForInStatement(variable, iterable, body, isAsync: isAsync)
      ..fileOffset = offset
      ..bodyOffset = bodyOffset
      ..scope = scope;
  }

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

  VariableStatement _readVariableStatement() {
    int offset = readOffset();
    VariableDeclaration declaration = readVariableDeclaration();
    return new VariableStatement(declaration)..fileOffset = offset;
  }

  VariableDeclaration readVariableDeclaration() {
    int tag = readByte();
    assert(tag == Tag.VariableDeclaration);
    int offset = readOffset();
    List<VariableContext>? capturedContexts = readOptionalCapturedContexts();
    DeclaredVariable variable = readDeclaredVariable();
    variableStack.add(variable); // Will be popped by the enclosing scope.
    return new VariableDeclaration(variable)
      ..fileOffset = offset
      ..capturedContexts = capturedContexts;
  }

  Statement _readFunctionDeclaration() {
    int offset = readOffset();
    LocalFunctionVariable variable = readLocalFunctionVariable();
    variableStack.add(variable); // Will be popped by the enclosing scope.
    final LocalFunctionId id = LocalFunctionId(readUInt30());
    return new FunctionDeclaration(variable, readFunctionNode().functionNode)
      ..fileOffset = offset
      ..id = id;
  }

  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();
    int scopeSize = readScopeSizeAndAllocateContexts();
    DartType guard = readDartType();
    CatchVariable? exception = readAndPushVariableOption() as CatchVariable?;
    CatchVariable? stackTrace = readAndPushVariableOption() as CatchVariable?;
    Statement body = readStatement();
    Scope? scope = readOptionalScope(scopeSize);
    variableStack.length = variableStackHeight;
    return new Catch(exception, body, guard: guard, stackTrace: stackTrace)
      ..fileOffset = offset
      ..scope = scope;
  }

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

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

  DartTypeList readDartTypeList() {
    int length = readUInt30();
    return DartTypeList.generate(length, (_) => readDartType());
  }

  NamedDartTypeList readNamedTypeList() {
    int length = readUInt30();
    return NamedDartTypeList.generate(length, (_) => readNamedType());
  }

  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();
    DartTypeList 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],
      DartTypeList.empty,
    );
    _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();
    DartTypeList typeArguments = readDartTypeList();
    readDartType(); // Read type erasure.
    return new ExtensionType.byReference(
      reference,
      Nullability.values[nullabilityIndex],
      typeArguments,
    );
  }

  DartType _readFunctionType() {
    int typeParameterStackHeight = typeParameterStack.length;
    int nullabilityIndex = readByte();
    StructuralParameterList typeParameters =
        readAndPushStructuralParameterList();
    int requiredParameterCount = readUInt30();
    int totalParameterCount = readUInt30();
    DartTypeList positional = readDartTypeList();
    NamedDartTypeList 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();
    DartTypeList 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(
        DartTypeList.empty,
        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();
    DartTypeList positional = readDartTypeList();
    NamedDartTypeList 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;
  }

  StructuralParameterList readAndPushStructuralParameterList() {
    int length = readUInt30();
    if (length == 0) {
      return StructuralParameterList.empty;
    }
    StructuralParameterList list = StructuralParameterList.generate(
      length,
      (_) => 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();
    DartTypeList typeArguments = readDartTypeList();
    int numPositional = readUInt30();
    ExpressionList positional = ExpressionList.generate(
      numPositional,
      (_) => readExpression(),
    );
    int numNamed = readUInt30();
    NamedExpressionList named = NamedExpressionList.generate(
      numNamed,
      (_) => readNamedExpression(),
    );
    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.generate(
      length,
      (int index) => readVariableDeclaration(),
      growable: useGrowableLists,
    );
  }

  List<DeclaredVariable> readAndPushDeclaredVariableList() {
    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 emptyListOfDeclaredVariable;
    }
    return new List<DeclaredVariable>.generate(
      length,
      (_) => readAndPushDeclaredVariable(),
      growable: useGrowableLists,
    );
  }

  List<PositionalParameter> readAndPushPositionalParameterList() {
    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 emptyListOfPositionalParameter;
    }
    return new List<PositionalParameter>.generate(
      length,
      (_) => readAndPushPositionalParameter(),
      growable: useGrowableLists,
    );
  }

  List<NamedParameter> readAndPushNamedParameterList() {
    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 emptyListOfNamedParameter;
    }
    return new List<NamedParameter>.generate(
      length,
      (_) => readAndPushNamedParameter(),
      growable: useGrowableLists,
    );
  }

  Variable? readAndPushVariableOption() {
    return readAndCheckOptionTag() ? readAndPushVariable() : null;
  }

  Variable readAndPushVariable() {
    Variable variable = readVariable();
    variableStack.add(variable);
    return variable;
  }

  DeclaredVariable readAndPushDeclaredVariable() {
    DeclaredVariable variable = readDeclaredVariable();
    variableStack.add(variable);
    return variable;
  }

  PositionalParameter readAndPushPositionalParameter() {
    PositionalParameter variable = readPositionalParameter();
    variableStack.add(variable);
    return variable;
  }

  NamedParameter readAndPushNamedParameter() {
    NamedParameter variable = readNamedParameter();
    variableStack.add(variable);
    return variable;
  }

  DeclaredVariable readDeclaredVariable() {
    return readVariable() as DeclaredVariable;
  }

  PositionalParameter readPositionalParameter() {
    return readVariable() as PositionalParameter;
  }

  NamedParameter readNamedParameter() {
    return readVariable() as NamedParameter;
  }

  LocalFunctionVariable readLocalFunctionVariable() {
    return readVariable() as LocalFunctionVariable;
  }

  Variable readVariable() {
    int tag = readByte();
    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();
    String? name = readStringOrNullIfEmpty();
    DartType type = readDartType();
    Expression? initializer = readExpressionOption();
    Variable node;
    switch (tag) {
      case Tag.LocalVariable:
        node =
            new LocalVariable(name: name!, type: type, initializer: initializer)
              ..flags = flags
              ..fileOffset = offset
              ..fileEqualsOffset = fileEqualsOffset;
      case Tag.LateVariable:
        node =
            new LateVariable(name: name!, type: type, initialValue: initializer)
              ..flags = flags
              ..fileOffset = offset
              ..fileEqualsOffset = fileEqualsOffset;
      case Tag.LocalFunctionVariable:
        assert(
          initializer == null,
          "Unexpected initializer on LocalFunctionVariable",
        );
        node = new LocalFunctionVariable(name: name!, type: type)
          ..flags = flags
          ..fileOffset = offset
          ..fileEqualsOffset = fileEqualsOffset;
      case Tag.ConstVariable:
        node = new ConstVariable(name: name!, type: type, value: initializer)
          ..flags = flags
          ..fileOffset = offset
          ..fileEqualsOffset = fileEqualsOffset;
      case Tag.SyntheticVariable:
        node =
            new SyntheticVariable(
                cosmeticName: name,
                type: type,
                initializer: initializer,
              )
              ..flags = flags
              ..fileOffset = offset
              ..fileEqualsOffset = fileEqualsOffset;
      case Tag.CatchVariable:
        assert(initializer == null, "Unexpected initializer on CatchVariable");
        node = new CatchVariable(name: name!, type: type)
          ..flags = flags
          ..fileOffset = offset
          ..fileEqualsOffset = fileEqualsOffset;
      case Tag.PositionalParameter:
        node =
            new PositionalParameter(
                parameterName: name!,
                type: type,
                defaultValue: initializer,
              )
              ..flags = flags
              ..fileOffset = offset
              ..fileEqualsOffset = fileEqualsOffset;
      case Tag.NamedParameter:
        node =
            new NamedParameter(
                parameterName: name!,
                type: type,
                defaultValue: initializer,
              )
              ..flags = flags
              ..fileOffset = offset
              ..fileEqualsOffset = fileEqualsOffset;
      case Tag.ThisVariable:
        assert(name == null, "Unexpected name on ThisVariable.");
        assert(initializer == null, "Unexpected initializer on ThisVariable.");
        node = new ThisVariable(type: type)
          ..flags = flags
          ..fileOffset = offset
          ..fileEqualsOffset = fileEqualsOffset;
      default:
        throw new UnsupportedError("Unexpected variable tag $tag");
    }

    if (annotations.isNotEmpty) {
      for (int i = 0; i < annotations.length; ++i) {
        Expression annotation = annotations[i];
        annotation.parent = node;
      }
      node.annotations = annotations;
    }
    return node;
  }

  List<VariableContext>? readOptionalCapturedContexts() {
    return readAndCheckOptionTag() ? readCapturedContexts() : null;
  }

  List<VariableContext> readCapturedContexts() {
    int length = readUInt30();
    return new List<VariableContext>.generate(
      length,
      (_) => readVariableContextReference(),
      growable: useGrowableLists,
    );
  }

  VariableContext readVariableContextReference() {
    int index = readUInt30();
    if (index >= variableContextStack.length) {
      throw fail(
        'Unexpected variable context index: $index. '
        'Current variable context count: ${variableContextStack.length}.',
      );
    }
    return variableContextStack[index];
  }

  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;

  new(
    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
  FunctionNodeAndContexts readFunctionNode({
    bool lazyLoadBody = false,
    int outerEndOffset = -1,
  }) {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final FunctionNodeAndContexts result = super.readFunctionNode(
      lazyLoadBody: lazyLoadBody,
      outerEndOffset: outerEndOffset,
    );
    return hasMetadata
        ? new FunctionNodeAndContexts(
            _associateMetadata(result.functionNode, nodeOffset),
            result.preAllocatedContexts,
          )
        : 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
  Variable readVariable() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final Variable result = super.readVariable();
    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
  VariableDeclaration readVariableDeclaration() {
    final int nodeOffset = _byteOffset;
    final bool hasMetadata = _hasMetadata(_byteOffset);
    final VariableDeclaration result = super.readVariableDeclaration();
    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(this.repository, this.mapping) {
  /// [MetadataRepository] that can read this subsection.
  final MetadataRepository repository;

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

/// Result of reading a function node and allocating its scope.
///
/// Function nodes with lazily loaded bodies have empty scopes immediately after
/// the moment of reading, even though the scope may be not empty after loading
/// the body. This helper class holds both the read function (potentially,
/// without the body and the scope) and the pre-allocated variable contexts from
/// the scope.
class FunctionNodeAndContexts(this.functionNode, this.preAllocatedContexts) {
  final FunctionNode functionNode;
  final List<VariableContext>? preAllocatedContexts;
}
