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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    // Skip to the start of the index.
    _byteOffset -= 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();
    return new LibraryPart(annotations, partUri);
  }

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

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

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

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

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

    assert(typeParameterStack.length == 0);

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

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

    _byteOffset = endOffset;

    return node;
  }

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

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

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

    List<Expression> annotations = readAnnotationList();

    Uri fileUri = readUriReference();

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

    node.fileOffset = readOffset();

    node.flags = readByte();

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

    typeParameterStack.length = 0;

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

    node.memberDescriptors = _readExtensionMemberDescriptorList();

    return node;
  }

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

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

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

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

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

    List<Expression> annotations = readAnnotationList();

    Uri fileUri = readUriReference();

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

    node.fileOffset = readOffset();

    node.flags = readByte();

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

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

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

    node.implements = implements;

    node.memberDescriptors = _readExtensionTypeMemberDescriptorList();

    return node;
  }

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

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

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

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

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

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

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

  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();
    return new LocalInitializer(readAndPushVariable() as SyntheticVariable)
      ..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();
      List<DartType>? typeArguments;
      if (readAndCheckOptionTag()) {
        typeArguments = readDartTypeList();
      }
      if (readAndCheckOptionTag()) {
        assert(targetReference == null && typeArguments == null);
        String errorMessage = readStringReference();
        redirectingFactoryTarget = new RedirectingFactoryTarget.error(
          errorMessage,
        );
      } else {
        assert(targetReference != null && typeArguments != null);
        redirectingFactoryTarget = new RedirectingFactoryTarget.byReference(
          targetReference!,
          typeArguments!,
        );
      }
    }

    int oldLabelStackBase = labelStackBase;
    int oldSwitchCaseStackBase = switchCaseStackBase;

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

    Statement? body;
    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();
    List<StructuralParameter> structuralParameters =
        readAndPushStructuralParameterList();
    Expression expression = readExpression();
    List<DartType> typeArguments = readDartTypeList();
    typeParameterStack.length -= structuralParameters.length;
    return new TypedefTearOff(structuralParameters, expression, typeArguments)
      ..fileOffset = offset;
  }

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

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

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

  Expression _readInstanceInvocation() {
    InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
    int flags = readByte();
    int offset = readOffset();
    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();
    List<DartType> typeArguments = readDartTypeList();
    int fieldValueCount = readUInt30();
    Map<Reference, Expression> fieldValues = <Reference, Expression>{};
    for (int i = 0; i < fieldValueCount; i++) {
      final Reference fieldRef = readNonNullCanonicalNameReference().reference;
      final Expression value = readExpression();
      fieldValues[fieldRef] = value;
    }
    int assertCount = readUInt30();
    List<AssertStatement> asserts;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  Expression _readFunctionExpression() {
    int offset = readOffset();
    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;
    return new Let(variable, 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();
    List<DartType> typeArguments = readDartTypeList();
    return new Instantiation(expression, typeArguments)..fileOffset = offset;
  }

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

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

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

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

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

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

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

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

  List<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();
    Variable variable = readVariableReference();
    Variable? setter = readVariableReferenceOption();
    DartType? matchedType = readDartTypeOption();
    bool needsCheck = readByte() == 1;
    return AssignedVariablePattern(variable)
      ..fileOffset = fileOffset
      ..matchedValueType = matchedType
      ..needsCast = needsCheck
      ..setter = setter;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  void _readPatternSwitchCaseInto(PatternSwitchCase caseNode) {
    int variableCount = readUInt30();
    for (int i = 0; i < variableCount; ++i) {
      caseNode.jointVariables.add(readDeclaredVariable()..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,
      );
    }
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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