// Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:typed_data' show Uint8List;

import 'package:kernel/ast.dart' show TreeNode, listHashCode, listEquals;
import 'package:kernel/core_types.dart' show CoreTypes;
import 'bytecode_serialization.dart'
    show
        BufferedWriter,
        BufferedReader,
        BytecodeDeclaration,
        BytecodeSizeStatistics,
        StringTable;
import 'constant_pool.dart' show ConstantPool;
import 'dbc.dart' show bytecodeFormatVersion;
import 'disassembler.dart' show BytecodeDisassembler;
import 'exceptions.dart' show ExceptionsTable;
import 'local_variable_table.dart' show LocalVariableTable;
import 'object_table.dart'
    show
        ObjectTable,
        ObjectHandle,
        NameAndType,
        ParameterFlags,
        TypeParameterDeclaration;
import 'source_positions.dart' show LineStarts, SourcePositions;

class LibraryDeclaration extends BytecodeDeclaration {
  static const usesDartMirrorsFlag = 1 << 0;
  static const usesDartFfiFlag = 1 << 1;

  ObjectHandle? importUri;
  final int flags;
  final ObjectHandle name;
  final ObjectHandle script;
  final List<ClassDeclaration> classes;

  LibraryDeclaration(
      this.importUri, this.flags, this.name, this.script, this.classes);

  void write(BufferedWriter writer) {
    final start = writer.offset;
    writer.writePackedUInt30(flags);
    writer.writePackedObject(name);
    writer.writePackedObject(script);
    writer.writePackedUInt30(classes.length);
    for (var cls in classes) {
      writer.writePackedObject(cls.name!);
      writer.writeLinkOffset(cls);
    }
    BytecodeSizeStatistics.librariesSize += (writer.offset - start);
  }

  factory LibraryDeclaration.read(BufferedReader reader) {
    final flags = reader.readPackedUInt30();
    final ObjectHandle name = reader.readPackedObject();
    final ObjectHandle script = reader.readPackedObject();
    final classes =
        List<ClassDeclaration>.generate(reader.readPackedUInt30(), (_) {
      final ObjectHandle className = reader.readPackedObject();
      return reader.readLinkOffset<ClassDeclaration>()..name = className;
    });
    return new LibraryDeclaration(null, flags, name, script, classes);
  }

  @override
  String toString() {
    final StringBuffer sb = new StringBuffer();
    sb.writeln('Library $importUri');
    sb.writeln('    name $name');
    sb.writeln('    script $script');
    if ((flags & usesDartMirrorsFlag) != 0) {
      sb.writeln('    uses dart:mirrors');
    }
    if ((flags & usesDartFfiFlag) != 0) {
      sb.writeln('    uses dart:ffi');
    }
    sb.writeln();
    for (var cls in classes) {
      sb.write(cls);
    }
    return sb.toString();
  }
}

class ClassDeclaration extends BytecodeDeclaration {
  static const isAbstractFlag = 1 << 0;
  static const isEnumFlag = 1 << 1;
  static const hasTypeParamsFlag = 1 << 2;
  static const hasTypeArgumentsFlag = 1 << 3;
  static const isTransformedMixinApplicationFlag = 1 << 4;
  static const hasSourcePositionsFlag = 1 << 5;
  static const hasAnnotationsFlag = 1 << 6;
  static const hasPragmaFlag = 1 << 7;
  static const hasConstConstructorFlag = 1 << 8;
  static const isSealedFlag = 1 << 9;
  static const isMixinClassFlag = 1 << 10;
  static const isBaseClassFlag = 1 << 11;
  static const isInterfaceFlag = 1 << 12;
  static const isFinalFlag = 1 << 13;

  ObjectHandle? name;
  final int flags;
  final ObjectHandle script;
  final int position;
  final int endPosition;
  final TypeParametersDeclaration? typeParameters;
  final int numTypeArguments;
  final ObjectHandle? superType;
  final List<ObjectHandle> interfaces;
  final Members members;
  final AnnotationsDeclaration? annotations;

  ClassDeclaration(
      this.name,
      this.flags,
      this.script,
      this.position,
      this.endPosition,
      this.typeParameters,
      this.numTypeArguments,
      this.superType,
      this.interfaces,
      this.members,
      this.annotations);

  void write(BufferedWriter writer) {
    final start = writer.offset;
    writer.writePackedUInt30(flags);
    writer.writePackedObject(script);

    if ((flags & hasSourcePositionsFlag) != 0) {
      writer.writePackedUInt30(position + 1);
      writer.writePackedUInt30(endPosition + 1);
    }
    if ((flags & hasTypeArgumentsFlag) != 0) {
      writer.writePackedUInt30(numTypeArguments);
    }
    if ((flags & hasTypeParamsFlag) != 0) {
      typeParameters!.write(writer);
    }
    writer.writePackedObject(superType);
    writer.writePackedList(interfaces);
    if ((flags & hasAnnotationsFlag) != 0) {
      writer.writeLinkOffset(annotations!);
    }
    writer.writeLinkOffset(members);
    BytecodeSizeStatistics.classesSize += (writer.offset - start);
  }

  factory ClassDeclaration.read(BufferedReader reader) {
    final flags = reader.readPackedUInt30();
    final ObjectHandle script = reader.readPackedObject();
    final position = ((flags & hasSourcePositionsFlag) != 0)
        ? reader.readPackedUInt30() - 1
        : TreeNode.noOffset;
    final endPosition = ((flags & hasSourcePositionsFlag) != 0)
        ? reader.readPackedUInt30() - 1
        : TreeNode.noOffset;
    final numTypeArguments =
        ((flags & hasTypeArgumentsFlag) != 0) ? reader.readPackedUInt30() : 0;
    final typeParameters = ((flags & hasTypeParamsFlag) != 0)
        ? new TypeParametersDeclaration.read(reader)
        : null;
    final ObjectHandle? superType = reader.readPackedObject();
    final interfaces = reader.readPackedList<ObjectHandle>();
    final annotations = ((flags & hasAnnotationsFlag) != 0)
        ? reader.readLinkOffset<AnnotationsDeclaration>()
        : null;
    final members = reader.readLinkOffset<Members>();
    return new ClassDeclaration(
        null,
        flags,
        script,
        position,
        endPosition,
        typeParameters,
        numTypeArguments,
        superType,
        interfaces,
        members,
        annotations);
  }

  @override
  String toString() {
    final StringBuffer sb = new StringBuffer();
    sb.write('Class $name, script = $script');
    if ((flags & isAbstractFlag) != 0) {
      sb.write(', abstract');
    }
    if ((flags & isEnumFlag) != 0) {
      sb.write(', enum');
    }
    if ((flags & isTransformedMixinApplicationFlag) != 0) {
      sb.write(', mixin-application');
    }
    if ((flags & hasPragmaFlag) != 0) {
      sb.write(', has-pragma');
    }
    if ((flags & hasSourcePositionsFlag) != 0) {
      sb.write(', pos = $position, end-pos = $endPosition');
    }
    sb.writeln();
    if ((flags & hasTypeParamsFlag) != 0) {
      sb.write('    type-params $typeParameters (args: $numTypeArguments)\n');
    }
    if (superType != null) {
      sb.write('    extends $superType\n');
    }
    if (interfaces.isNotEmpty) {
      sb.write('    implements $interfaces\n');
    }
    if ((flags & hasAnnotationsFlag) != 0) {
      sb.write('    annotations $annotations\n');
    }
    sb.writeln();
    sb.write(members.toString());
    return sb.toString();
  }
}

class SourceFile extends BytecodeDeclaration {
  static const hasLineStartsFlag = 1 << 0;
  static const hasSourceFlag = 1 << 1;

  final ObjectHandle importUri;
  LineStarts? lineStarts;
  String? source;

  SourceFile(this.importUri, [this.lineStarts, this.source]);

  void write(BufferedWriter writer) {
    int flags = 0;
    if (lineStarts != null) {
      flags |= hasLineStartsFlag;
    }
    if (source != null && source != '') {
      flags |= hasSourceFlag;
    }
    writer.writePackedUInt30(flags);
    writer.writePackedObject(importUri);
    if ((flags & hasLineStartsFlag) != 0) {
      writer.writeLinkOffset(lineStarts!);
    }
    if ((flags & hasSourceFlag) != 0) {
      writer.writePackedStringReference(source!);
    }
  }

  factory SourceFile.read(BufferedReader reader) {
    final flags = reader.readPackedUInt30();
    final ObjectHandle importUri = reader.readPackedObject();
    final lineStarts = ((flags & hasLineStartsFlag) != 0)
        ? reader.readLinkOffset<LineStarts>()
        : null;
    final source = ((flags & hasSourceFlag) != 0)
        ? reader.readPackedStringReference()
        : null;
    return new SourceFile(importUri, lineStarts, source);
  }

  @override
  String toString() {
    final StringBuffer sb = new StringBuffer();
    sb.write('source: import-uri $importUri');
    if (source != null && source != '') {
      sb.write(', ${source!.length} text chars');
    }
    if (lineStarts != null) {
      sb.write(', ${lineStarts!.lineStarts.length} line starts');
    }
    return sb.toString();
  }
}

class Members extends BytecodeDeclaration {
  final List<FieldDeclaration> fields;
  final List<FunctionDeclaration> functions;

  Members(this.fields, this.functions);

  int countFunctions() {
    int count = functions.length;
    for (var field in fields) {
      if ((field.flags & FieldDeclaration.hasGetterFlag) != 0) {
        ++count;
      }
      if ((field.flags & FieldDeclaration.hasSetterFlag) != 0) {
        ++count;
      }
    }
    return count;
  }

  void write(BufferedWriter writer) {
    final start = writer.offset;
    writer.writePackedUInt30(countFunctions());
    writer.writePackedUInt30(fields.length);
    for (var field in fields) {
      field.write(writer);
    }
    writer.writePackedUInt30(functions.length);
    for (var func in functions) {
      func.write(writer);
    }
    BytecodeSizeStatistics.membersSize += (writer.offset - start);
  }

  factory Members.read(BufferedReader reader) {
    reader.readPackedUInt30(); // numFunctions
    final fields = new List<FieldDeclaration>.generate(
        reader.readPackedUInt30(), (_) => new FieldDeclaration.read(reader));
    final functions = new List<FunctionDeclaration>.generate(
        reader.readPackedUInt30(), (_) => new FunctionDeclaration.read(reader));
    return new Members(fields, functions);
  }

  @override
  String toString() => "${fields.join('\n')}\n"
      "${functions.join('\n')}";
}

class FieldDeclaration {
  static const isStaticFlag = 1 << 0;
  static const isConstFlag = 1 << 1;
  static const isFinalFlag = 1 << 2;
  static const isLateFlag = 1 << 3;
  static const isCovariantFlag = 1 << 4;
  static const isCovariantByClassFlag = 1 << 5;
  static const isExtensionMemberFlag = 1 << 6;
  static const isReflectableFlag = 1 << 7;
  static const hasGetterFlag = 1 << 8;
  static const hasSetterFlag = 1 << 9;
  static const hasInitializerFlag = 1 << 10;
  static const hasNontrivialInitializerFlag = 1 << 11;
  static const hasInitializerCodeFlag = 1 << 12;
  static const hasSourcePositionsFlag = 1 << 13;
  static const hasAnnotationsFlag = 1 << 14;
  static const hasPragmaFlag = 1 << 15;
  static const hasCustomScriptFlag = 1 << 16;

  final int flags;
  final ObjectHandle name;
  final ObjectHandle type;
  final ObjectHandle? value;
  final ObjectHandle? script;
  final int position;
  final int endPosition;
  final ObjectHandle? getterName;
  final ObjectHandle? setterName;
  final Code? initializerCode;
  final AnnotationsDeclaration? annotations;

  FieldDeclaration(
      this.flags,
      this.name,
      this.type,
      this.value,
      this.script,
      this.position,
      this.endPosition,
      this.getterName,
      this.setterName,
      this.initializerCode,
      this.annotations);

  void write(BufferedWriter writer) {
    writer.writePackedUInt30(flags);
    writer.writePackedObject(name);
    writer.writePackedObject(type);

    if ((flags & hasCustomScriptFlag) != 0) {
      writer.writePackedObject(script);
    }
    if ((flags & hasSourcePositionsFlag) != 0) {
      writer.writePackedUInt30(position + 1);
      writer.writePackedUInt30(endPosition + 1);
    }
    if ((flags & hasInitializerCodeFlag) != 0) {
      writer.writeLinkOffset(initializerCode!);
    }
    if ((flags & hasNontrivialInitializerFlag) == 0) {
      writer.writePackedObject(value);
    }
    if ((flags & hasGetterFlag) != 0) {
      writer.writePackedObject(getterName);
    }
    if ((flags & hasSetterFlag) != 0) {
      writer.writePackedObject(setterName);
    }
    if ((flags & hasAnnotationsFlag) != 0) {
      writer.writeLinkOffset(annotations!);
    }
  }

  factory FieldDeclaration.read(BufferedReader reader) {
    final flags = reader.readPackedUInt30();
    final ObjectHandle name = reader.readPackedObject();
    final ObjectHandle type = reader.readPackedObject();
    final script = ((flags & hasCustomScriptFlag) != 0)
        ? reader.readPackedObject<ObjectHandle>()
        : null;
    final position = ((flags & hasSourcePositionsFlag) != 0)
        ? reader.readPackedUInt30() - 1
        : TreeNode.noOffset;
    final endPosition = ((flags & hasSourcePositionsFlag) != 0)
        ? reader.readPackedUInt30() - 1
        : TreeNode.noOffset;
    final initializerCode = ((flags & hasInitializerCodeFlag) != 0)
        ? reader.readLinkOffset<Code>()
        : null;
    final value = ((flags & hasNontrivialInitializerFlag) == 0)
        ? reader.readPackedObject<ObjectHandle?>()
        : null;
    final getterName = ((flags & hasGetterFlag) != 0)
        ? reader.readPackedObject<ObjectHandle>()
        : null;
    final setterName = ((flags & hasSetterFlag) != 0)
        ? reader.readPackedObject<ObjectHandle>()
        : null;
    final annotations = ((flags & hasAnnotationsFlag) != 0)
        ? reader.readLinkOffset<AnnotationsDeclaration>()
        : null;
    return new FieldDeclaration(flags, name, type, value, script, position,
        endPosition, getterName, setterName, initializerCode, annotations);
  }

  @override
  String toString() {
    final StringBuffer sb = new StringBuffer();
    sb.write('Field $name, type = $type');
    if ((flags & hasGetterFlag) != 0) {
      sb.write(', getter = $getterName');
    }
    if ((flags & hasSetterFlag) != 0) {
      sb.write(', setter = $setterName');
    }
    if ((flags & isReflectableFlag) != 0) {
      sb.write(', reflectable');
    }
    if ((flags & isStaticFlag) != 0) {
      sb.write(', static');
    }
    if ((flags & isConstFlag) != 0) {
      sb.write(', const');
    }
    if ((flags & isFinalFlag) != 0) {
      sb.write(', final');
    }
    if ((flags & isLateFlag) != 0) {
      sb.write(', is-late');
    }
    if ((flags & isExtensionMemberFlag) != 0) {
      sb.write(', extension-member');
    }
    if ((flags & hasPragmaFlag) != 0) {
      sb.write(', has-pragma');
    }
    if ((flags & hasCustomScriptFlag) != 0) {
      sb.write(', custom-script = $script');
    }
    if ((flags & hasSourcePositionsFlag) != 0) {
      sb.write(', pos = $position, end-pos = $endPosition');
    }
    if ((flags & hasInitializerFlag) != 0) {
      sb.write(', has-initializer');
    }
    sb.writeln();
    if ((flags & hasInitializerCodeFlag) != 0) {
      sb.write('    initializer\n$initializerCode\n');
    }
    if ((flags & hasNontrivialInitializerFlag) == 0) {
      sb.write('    value = $value\n');
    }
    if ((flags & hasAnnotationsFlag) != 0) {
      sb.write('    annotations $annotations\n');
    }
    return sb.toString();
  }
}

class FunctionDeclaration {
  static const isStaticFlag = 1 << 0;
  static const isAbstractFlag = 1 << 1;
  static const isGetterFlag = 1 << 2;
  static const isSetterFlag = 1 << 3;
  static const isConstructorFlag = 1 << 4;
  static const isFactoryFlag = 1 << 5;
  static const isConstFlag = 1 << 6;
  static const hasOptionalPositionalParamsFlag = 1 << 7;
  static const hasOptionalNamedParamsFlag = 1 << 8;
  static const hasTypeParamsFlag = 1 << 9;
  static const hasParameterFlagsFlag = 1 << 10;
  static const isExtensionMemberFlag = 1 << 11;
  static const isReflectableFlag = 1 << 12;
  static const isDebuggableFlag = 1 << 13;
  static const isAsyncFlag = 1 << 14;
  static const isAsyncStarFlag = 1 << 15;
  static const isSyncStarFlag = 1 << 16;
  static const isNoSuchMethodForwarderFlag = 1 << 17;
  static const isExternalFlag = 1 << 18;
  static const isNativeFlag = 1 << 19;
  static const hasSourcePositionsFlag = 1 << 20;
  static const hasAnnotationsFlag = 1 << 21;
  static const hasPragmaFlag = 1 << 22;
  static const hasCustomScriptFlag = 1 << 23;

  final int flags;
  final ObjectHandle name;
  final ObjectHandle? script;
  final int position;
  final int endPosition;
  final TypeParametersDeclaration? typeParameters;
  final int numRequiredParameters;
  final List<ParameterDeclaration> parameters;
  // Only contains the required flag for named parameters when present.
  final List<int>? parameterFlags;
  final ObjectHandle returnType;
  final ObjectHandle? nativeName;
  final Code? code;
  final AnnotationsDeclaration? annotations;

  FunctionDeclaration(
      this.flags,
      this.name,
      this.script,
      this.position,
      this.endPosition,
      this.typeParameters,
      this.numRequiredParameters,
      this.parameters,
      this.parameterFlags,
      this.returnType,
      this.nativeName,
      this.code,
      this.annotations);

  void write(BufferedWriter writer) {
    writer.writePackedUInt30(flags);
    writer.writePackedObject(name);
    if ((flags & hasCustomScriptFlag) != 0) {
      writer.writePackedObject(script);
    }
    if ((flags & hasSourcePositionsFlag) != 0) {
      writer.writePackedUInt30(position + 1);
      writer.writePackedUInt30(endPosition + 1);
    }
    if ((flags & hasTypeParamsFlag) != 0) {
      typeParameters!.write(writer);
    }
    writer.writePackedUInt30(parameters.length);
    if ((flags & hasOptionalPositionalParamsFlag) != 0 ||
        (flags & hasOptionalNamedParamsFlag) != 0) {
      writer.writePackedUInt30(numRequiredParameters);
    }
    for (var param in parameters) {
      param.write(writer);
    }
    if ((flags & hasParameterFlagsFlag) != 0) {
      final parameterFlags = this.parameterFlags!;
      writer.writePackedUInt30(parameterFlags.length);
      parameterFlags.forEach((flags) => writer.writePackedUInt30(flags));
    }
    writer.writePackedObject(returnType);
    if ((flags & isNativeFlag) != 0) {
      writer.writePackedObject(nativeName);
    }
    if ((flags & isAbstractFlag) == 0) {
      writer.writeLinkOffset(code!);
    }
    if ((flags & hasAnnotationsFlag) != 0) {
      writer.writeLinkOffset(annotations!);
    }
  }

  factory FunctionDeclaration.read(BufferedReader reader) {
    final flags = reader.readPackedUInt30();
    final ObjectHandle name = reader.readPackedObject();

    final script = ((flags & hasCustomScriptFlag) != 0)
        ? reader.readPackedObject<ObjectHandle>()
        : null;
    final position = ((flags & hasSourcePositionsFlag) != 0)
        ? reader.readPackedUInt30() - 1
        : TreeNode.noOffset;
    final endPosition = ((flags & hasSourcePositionsFlag) != 0)
        ? reader.readPackedUInt30() - 1
        : TreeNode.noOffset;
    final typeParameters = ((flags & hasTypeParamsFlag) != 0)
        ? new TypeParametersDeclaration.read(reader)
        : null;

    final numParameters = reader.readPackedUInt30();
    final numRequiredParameters =
        ((flags & hasOptionalPositionalParamsFlag) != 0 ||
                (flags & hasOptionalNamedParamsFlag) != 0)
            ? reader.readPackedUInt30()
            : numParameters;

    final parameters = new List<ParameterDeclaration>.generate(
        numParameters, (_) => new ParameterDeclaration.read(reader));
    final parameterFlags = ((flags & hasParameterFlagsFlag) != 0)
        ? List<int>.generate(
            reader.readPackedUInt30(), (_) => reader.readPackedUInt30())
        : null;
    final ObjectHandle returnType = reader.readPackedObject();
    final nativeName = ((flags & isNativeFlag) != 0)
        ? reader.readPackedObject<ObjectHandle>()
        : null;
    final code =
        ((flags & isAbstractFlag) == 0) ? reader.readLinkOffset<Code>() : null;
    final annotations = ((flags & hasAnnotationsFlag) != 0)
        ? reader.readLinkOffset<AnnotationsDeclaration>()
        : null;
    return new FunctionDeclaration(
        flags,
        name,
        script,
        position,
        endPosition,
        typeParameters,
        numRequiredParameters,
        parameters,
        parameterFlags,
        returnType,
        nativeName,
        code,
        annotations);
  }

  @override
  String toString() {
    final StringBuffer sb = new StringBuffer();
    sb.write('Function $name');
    if ((flags & isConstructorFlag) != 0) {
      sb.write(', constructor');
    }
    if ((flags & isGetterFlag) != 0) {
      sb.write(', getter');
    }
    if ((flags & isSetterFlag) != 0) {
      sb.write(', setter');
    }
    if ((flags & isFactoryFlag) != 0) {
      sb.write(', factory');
    }
    if ((flags & isStaticFlag) != 0) {
      sb.write(', static');
    }
    if ((flags & isAbstractFlag) != 0) {
      sb.write(', abstract');
    }
    if ((flags & isConstFlag) != 0) {
      sb.write(', const');
    }
    if ((flags & isExtensionMemberFlag) != 0) {
      sb.write(', extension-member');
    }
    if ((flags & hasOptionalPositionalParamsFlag) != 0) {
      sb.write(', has-optional-positional-params');
    }
    if ((flags & hasOptionalNamedParamsFlag) != 0) {
      sb.write(', has-optional-named-params');
    }
    if ((flags & isReflectableFlag) != 0) {
      sb.write(', reflectable');
    }
    if ((flags & isDebuggableFlag) != 0) {
      sb.write(', debuggable');
    }
    if ((flags & isAsyncFlag) != 0) {
      sb.write(', async');
    }
    if ((flags & isAsyncStarFlag) != 0) {
      sb.write(', async*');
    }
    if ((flags & isSyncStarFlag) != 0) {
      sb.write(', sync*');
    }
    if ((flags & isNoSuchMethodForwarderFlag) != 0) {
      sb.write(', no-such-method-forwarder');
    }
    if ((flags & isNativeFlag) != 0) {
      sb.write(', native $nativeName');
    }
    if ((flags & isExternalFlag) != 0) {
      sb.write(', external');
    }
    if ((flags & hasPragmaFlag) != 0) {
      sb.write(', has-pragma');
    }
    if ((flags & hasCustomScriptFlag) != 0) {
      sb.write(', custom-script = $script');
    }
    if ((flags & hasSourcePositionsFlag) != 0) {
      sb.write(', pos = $position, end-pos = $endPosition');
    }
    sb.writeln();
    if ((flags & hasTypeParamsFlag) != 0) {
      sb.write('    type-params $typeParameters\n');
    }
    sb.write('    parameters $parameters (required: $numRequiredParameters)\n');
    if ((flags & hasParameterFlagsFlag) != 0) {
      sb.write('    parameter-flags $parameterFlags\n');
    }
    sb.write('    return-type $returnType\n');
    if ((flags & hasAnnotationsFlag) != 0) {
      sb.write('    annotations $annotations\n');
    }
    if ((flags & isAbstractFlag) == 0 && (flags & isExternalFlag) == 0) {
      sb.write('\n$code\n');
    }
    return sb.toString();
  }
}

class TypeParametersDeclaration {
  final List<TypeParameterDeclaration> typeParams;

  TypeParametersDeclaration(this.typeParams);

  void write(BufferedWriter writer) {
    writer.writePackedUInt30(typeParams.length);
    for (var tp in typeParams) {
      writer.writePackedObject(tp.name);
    }
    for (var tp in typeParams) {
      writer.writePackedObject(tp.bound);
      writer.writePackedObject(tp.defaultType);
    }
  }

  factory TypeParametersDeclaration.read(BufferedReader reader) {
    final int numTypeParams = reader.readPackedUInt30();
    final names = List<ObjectHandle>.generate(
        numTypeParams, (_) => reader.readPackedObject());
    return TypeParametersDeclaration(List<TypeParameterDeclaration>.generate(
        numTypeParams,
        (int i) => TypeParameterDeclaration(
            names[i], reader.readPackedObject(), reader.readPackedObject())));
  }

  @override
  int get hashCode => listHashCode(typeParams);

  @override
  bool operator ==(other) =>
      other is TypeParametersDeclaration &&
      listEquals(this.typeParams, other.typeParams);

  @override
  String toString() => '<${typeParams.join(', ')}>';
}

class ParameterDeclaration {
  final ObjectHandle name;
  final ObjectHandle type;

  ParameterDeclaration(this.name, this.type);

  void write(BufferedWriter writer) {
    writer.writePackedObject(name);
    writer.writePackedObject(type);
  }

  factory ParameterDeclaration.read(BufferedReader reader) {
    final ObjectHandle name = reader.readPackedObject();
    final ObjectHandle type = reader.readPackedObject();
    return new ParameterDeclaration(name, type);
  }

  @override
  String toString() => '$type $name';
}

class Code extends BytecodeDeclaration {
  static const hasExceptionsTableFlag = 1 << 0;
  static const hasSourcePositionsFlag = 1 << 1;
  static const hasNullableFieldsFlag = 1 << 2;
  static const hasClosuresFlag = 1 << 3;
  static const hasParameterFlagsFlag = 1 << 4;
  static const hasForwardingStubTargetFlag = 1 << 5;
  static const hasDefaultFunctionTypeArgsFlag = 1 << 6;
  static const hasLocalVariablesFlag = 1 << 7;

  final ConstantPool constantPool;
  final Uint8List bytecodes;
  final ExceptionsTable exceptionsTable;
  final SourcePositions? sourcePositions;
  final LocalVariableTable? localVariables;
  final List<ObjectHandle> nullableFields;
  final List<ClosureDeclaration> closures;
  // Covariant and CovariantByClass flags for all parameters.
  final List<int>? parameterFlags;
  final int? forwardingStubTargetCpIndex;
  final int? defaultFunctionTypeArgsCpIndex;

  bool get hasExceptionsTable => exceptionsTable.blocks.isNotEmpty;
  bool get hasSourcePositions => sourcePositions?.isNotEmpty ?? false;
  bool get hasLocalVariables => localVariables?.isNotEmpty ?? false;
  bool get hasNullableFields => nullableFields.isNotEmpty;
  bool get hasClosures => closures.isNotEmpty;

  int get flags =>
      (hasExceptionsTable ? hasExceptionsTableFlag : 0) |
      (hasSourcePositions ? hasSourcePositionsFlag : 0) |
      (hasNullableFields ? hasNullableFieldsFlag : 0) |
      (hasClosures ? hasClosuresFlag : 0) |
      (parameterFlags != null ? hasParameterFlagsFlag : 0) |
      (forwardingStubTargetCpIndex != null ? hasForwardingStubTargetFlag : 0) |
      (defaultFunctionTypeArgsCpIndex != null
          ? hasDefaultFunctionTypeArgsFlag
          : 0) |
      (hasLocalVariables ? hasLocalVariablesFlag : 0);

  Code(
      this.constantPool,
      this.bytecodes,
      this.exceptionsTable,
      this.sourcePositions,
      this.localVariables,
      this.nullableFields,
      this.closures,
      this.parameterFlags,
      this.forwardingStubTargetCpIndex,
      this.defaultFunctionTypeArgsCpIndex);

  void write(BufferedWriter writer) {
    final start = writer.offset;
    writer.writePackedUInt30(flags);
    final parameterFlags = this.parameterFlags;
    if (parameterFlags != null) {
      writer.writePackedUInt30(parameterFlags.length);
      parameterFlags.forEach((flags) => writer.writePackedUInt30(flags));
    }
    final forwardingStubTargetCpIndex = this.forwardingStubTargetCpIndex;
    if (forwardingStubTargetCpIndex != null) {
      writer.writePackedUInt30(forwardingStubTargetCpIndex);
    }
    final defaultFunctionTypeArgsCpIndex = this.defaultFunctionTypeArgsCpIndex;
    if (defaultFunctionTypeArgsCpIndex != null) {
      writer.writePackedUInt30(defaultFunctionTypeArgsCpIndex);
    }
    if (hasClosures) {
      writer.writePackedUInt30(closures.length);
      closures.forEach((c) => c.write(writer));
    }
    constantPool.write(writer);
    _writeBytecodeInstructions(writer, bytecodes);
    if (hasExceptionsTable) {
      exceptionsTable.write(writer);
    }
    if (hasSourcePositions) {
      writer.writeLinkOffset(sourcePositions!);
    }
    if (hasLocalVariables) {
      writer.writeLinkOffset(localVariables!);
    }
    if (hasNullableFields) {
      writer.writePackedList(nullableFields);
    }
    if (hasClosures) {
      closures.forEach((c) => c.code!.write(writer));
    }
    BytecodeSizeStatistics.codeSize += (writer.offset - start);
  }

  factory Code.read(BufferedReader reader) {
    int flags = reader.readPackedUInt30();
    final parameterFlags = ((flags & hasParameterFlagsFlag) != 0)
        ? new List<int>.generate(
            reader.readPackedUInt30(), (_) => reader.readPackedUInt30())
        : null;
    final forwardingStubTargetCpIndex =
        ((flags & hasForwardingStubTargetFlag) != 0)
            ? reader.readPackedUInt30()
            : null;
    final defaultFunctionTypeArgsCpIndex =
        ((flags & hasDefaultFunctionTypeArgsFlag) != 0)
            ? reader.readPackedUInt30()
            : null;
    final List<ClosureDeclaration> closures = ((flags & hasClosuresFlag) != 0)
        ? new List<ClosureDeclaration>.generate(reader.readPackedUInt30(),
            (_) => new ClosureDeclaration.read(reader))
        : const <ClosureDeclaration>[];
    final ConstantPool constantPool = new ConstantPool.read(reader);
    final Uint8List bytecodes = _readBytecodeInstructions(reader);
    final exceptionsTable = ((flags & hasExceptionsTableFlag) != 0)
        ? new ExceptionsTable.read(reader)
        : new ExceptionsTable();
    final sourcePositions = ((flags & hasSourcePositionsFlag) != 0)
        ? reader.readLinkOffset<SourcePositions>()
        : null;
    final localVariables = ((flags & hasLocalVariablesFlag) != 0)
        ? reader.readLinkOffset<LocalVariableTable>()
        : null;
    final List<ObjectHandle> nullableFields =
        ((flags & hasNullableFieldsFlag) != 0)
            ? reader.readPackedList<ObjectHandle>()
            : const <ObjectHandle>[];
    for (var c in closures) {
      c.code = new ClosureCode.read(reader);
    }
    return new Code(
        constantPool,
        bytecodes,
        exceptionsTable,
        sourcePositions,
        localVariables,
        nullableFields,
        closures,
        parameterFlags,
        forwardingStubTargetCpIndex,
        defaultFunctionTypeArgsCpIndex);
  }

  // TODO(alexmarkov): Consider printing constant pool before bytecode.
  @override
  String toString() => "Bytecode {\n"
      "${new BytecodeDisassembler().disassemble(bytecodes, exceptionsTable, annotations: [
            hasSourcePositions
                ? sourcePositions!.getBytecodeAnnotations()
                : const <int, String>{},
            hasLocalVariables
                ? localVariables!.getBytecodeAnnotations()
                : const <int, String>{}
          ])}}\n"
      "$exceptionsTable"
      "${nullableFields.isEmpty ? '' : 'Nullable fields: $nullableFields\n'}"
      "${parameterFlags == null ? '' : 'Parameter flags: $parameterFlags\n'}"
      "${forwardingStubTargetCpIndex == null ? '' : 'Forwarding stub target: CP#$forwardingStubTargetCpIndex\n'}"
      "${defaultFunctionTypeArgsCpIndex == null ? '' : 'Default function type arguments: CP#$defaultFunctionTypeArgsCpIndex\n'}"
      "$constantPool"
      "${closures.join('\n')}";
}

class ClosureDeclaration {
  static const hasOptionalPositionalParamsFlag = 1 << 0;
  static const hasOptionalNamedParamsFlag = 1 << 1;
  static const hasTypeParamsFlag = 1 << 2;
  static const hasSourcePositionsFlag = 1 << 3;
  static const isAsyncFlag = 1 << 4;
  static const isAsyncStarFlag = 1 << 5;
  static const isSyncStarFlag = 1 << 6;
  static const isDebuggableFlag = 1 << 7;
  static const hasParameterFlagsFlag = 1 << 8;
  static const hasAnnotationsFlag = 1 << 9;
  static const hasPragmaFlag = 1 << 10;

  int flags;
  final ObjectHandle parent;
  final ObjectHandle name;
  final int position;
  final int endPosition;
  final TypeParametersDeclaration? typeParameters;
  final int numRequiredParams;
  final int numNamedParams;
  final List<NameAndType> parameters;
  // Only contains the required flag for named parameters when present.
  final List<int>? parameterFlags;
  final ObjectHandle returnType;
  final AnnotationsDeclaration? annotations;
  ClosureCode? code;

  ClosureDeclaration(
      this.flags,
      this.parent,
      this.name,
      this.position,
      this.endPosition,
      this.typeParameters,
      this.numRequiredParams,
      this.numNamedParams,
      this.parameters,
      this.parameterFlags,
      this.returnType,
      this.annotations);

  void write(BufferedWriter writer) {
    writer.writePackedUInt30(flags);
    writer.writePackedObject(parent);
    writer.writePackedObject(name);

    if (flags & hasSourcePositionsFlag != 0) {
      writer.writePackedUInt30(position + 1);
      writer.writePackedUInt30(endPosition + 1);
    }

    if (flags & hasTypeParamsFlag != 0) {
      typeParameters!.write(writer);
    }
    writer.writePackedUInt30(parameters.length);
    if (flags &
            (hasOptionalPositionalParamsFlag | hasOptionalNamedParamsFlag) !=
        0) {
      writer.writePackedUInt30(numRequiredParams);
    }
    for (var param in parameters) {
      writer.writePackedObject(param.name);
      writer.writePackedObject(param.type);
    }
    if ((flags & hasParameterFlagsFlag) != 0) {
      final parameterFlags = this.parameterFlags!;
      writer.writePackedUInt30(parameterFlags.length);
      for (var pf in parameterFlags) {
        writer.writePackedUInt30(pf);
      }
    }
    writer.writePackedObject(returnType);
    if ((flags & hasAnnotationsFlag) != 0) {
      writer.writeLinkOffset(annotations!);
    }
  }

  factory ClosureDeclaration.read(BufferedReader reader) {
    final int flags = reader.readPackedUInt30();
    final ObjectHandle parent = reader.readPackedObject();
    final ObjectHandle name = reader.readPackedObject();
    final position = ((flags & hasSourcePositionsFlag) != 0)
        ? reader.readPackedUInt30() - 1
        : TreeNode.noOffset;
    final endPosition = ((flags & hasSourcePositionsFlag) != 0)
        ? reader.readPackedUInt30() - 1
        : TreeNode.noOffset;
    final TypeParametersDeclaration? typeParameters =
        ((flags & hasTypeParamsFlag) != 0)
            ? TypeParametersDeclaration.read(reader)
            : null;
    final numParams = reader.readPackedUInt30();
    final numRequiredParams = (flags &
                (hasOptionalPositionalParamsFlag |
                    hasOptionalNamedParamsFlag) !=
            0)
        ? reader.readPackedUInt30()
        : numParams;
    final numNamedParams = (flags & hasOptionalNamedParamsFlag != 0)
        ? (numParams - numRequiredParams)
        : 0;
    final List<NameAndType> parameters = new List<NameAndType>.generate(
        numParams,
        (_) => new NameAndType(
            reader.readPackedObject(), reader.readPackedObject()));
    List<int>? parameterFlags;
    if ((flags & hasParameterFlagsFlag) != 0) {
      final int numParameterFlags = reader.readPackedUInt30();
      parameterFlags = List<int>.generate(
          numParameterFlags, (_) => reader.readPackedUInt30());
    }
    final ObjectHandle returnType = reader.readPackedObject();
    final annotations = ((flags & hasAnnotationsFlag) != 0)
        ? reader.readLinkOffset<AnnotationsDeclaration>()
        : null;
    return new ClosureDeclaration(
        flags,
        parent,
        name,
        position,
        endPosition,
        typeParameters,
        numRequiredParams,
        numNamedParams,
        parameters,
        parameterFlags,
        returnType,
        annotations);
  }

  void _writeParamsToBuffer(
      StringBuffer sb, List<NameAndType> params, List<int>? flags) {
    assert(flags == null || (params.length == flags.length));
    for (int i = 0; i < params.length; i++) {
      if (i != 0) {
        sb.write(', ');
      }
      // We only store the required flag for ClosureDeclarations.
      if (flags != null && (flags[i] & ParameterFlags.isRequiredFlag) != 0) {
        sb.write('required ');
      }
      sb.write(params[i]);
    }
  }

  @override
  String toString() {
    final StringBuffer sb = new StringBuffer();
    sb.write('Closure $parent::$name');
    if ((flags & isAsyncFlag) != 0) {
      sb.write(' async');
    }
    if ((flags & isAsyncStarFlag) != 0) {
      sb.write(' async*');
    }
    if ((flags & isSyncStarFlag) != 0) {
      sb.write(' sync*');
    }
    if (position != TreeNode.noOffset) {
      sb.write(' pos = $position, end-pos = $endPosition');
    }
    if ((flags & hasAnnotationsFlag) != 0) {
      sb.write(' annotations $annotations\n');
    }
    if ((flags & hasTypeParamsFlag) != 0) {
      sb.write(' type-params $typeParameters');
    }
    sb.write(' (');
    _writeParamsToBuffer(sb, parameters.sublist(0, numRequiredParams), null);
    if (numRequiredParams != parameters.length) {
      if (numRequiredParams > 0) {
        sb.write(', ');
      }
      sb.write(numNamedParams > 0 ? '{ ' : '[ ');
      _writeParamsToBuffer(
          sb, parameters.sublist(numRequiredParams), parameterFlags);
      sb.write(numNamedParams > 0 ? ' }' : ' ]');
    }
    sb.write(') -> ');
    sb.writeln(returnType);
    if (code != null) {
      sb.write(code.toString());
    }
    return sb.toString();
  }
}

/// Bytecode of a nested function (closure).
/// Closures share the constant pool of a top-level member.
class ClosureCode {
  static const hasExceptionsTableFlag = 1 << 0;
  static const hasSourcePositionsFlag = 1 << 1;
  static const hasLocalVariablesFlag = 1 << 2;

  final Uint8List bytecodes;
  final ExceptionsTable exceptionsTable;
  final SourcePositions? sourcePositions;
  final LocalVariableTable? localVariables;

  bool get hasExceptionsTable => exceptionsTable.blocks.isNotEmpty;
  bool get hasSourcePositions => sourcePositions?.isNotEmpty ?? false;
  bool get hasLocalVariables => localVariables?.isNotEmpty ?? false;

  int get flags =>
      (hasExceptionsTable ? hasExceptionsTableFlag : 0) |
      (hasSourcePositions ? hasSourcePositionsFlag : 0) |
      (hasLocalVariables ? hasLocalVariablesFlag : 0);

  ClosureCode(this.bytecodes, this.exceptionsTable, this.sourcePositions,
      this.localVariables);

  void write(BufferedWriter writer) {
    writer.writePackedUInt30(flags);
    _writeBytecodeInstructions(writer, bytecodes);
    if (hasExceptionsTable) {
      exceptionsTable.write(writer);
    }
    if (hasSourcePositions) {
      writer.writeLinkOffset(sourcePositions!);
    }
    if (hasLocalVariables) {
      writer.writeLinkOffset(localVariables!);
    }
  }

  factory ClosureCode.read(BufferedReader reader) {
    final int flags = reader.readPackedUInt30();
    final Uint8List bytecodes = _readBytecodeInstructions(reader);
    final exceptionsTable = ((flags & hasExceptionsTableFlag) != 0)
        ? new ExceptionsTable.read(reader)
        : new ExceptionsTable();
    final sourcePositions = ((flags & hasSourcePositionsFlag) != 0)
        ? reader.readLinkOffset<SourcePositions>()
        : null;
    final localVariables = ((flags & hasLocalVariablesFlag) != 0)
        ? reader.readLinkOffset<LocalVariableTable>()
        : null;
    return new ClosureCode(
        bytecodes, exceptionsTable, sourcePositions, localVariables);
  }

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.writeln('ClosureCode {');
    sb.write(new BytecodeDisassembler()
        .disassemble(bytecodes, exceptionsTable, annotations: [
      hasSourcePositions
          ? sourcePositions!.getBytecodeAnnotations()
          : const <int, String>{},
      hasLocalVariables
          ? localVariables!.getBytecodeAnnotations()
          : const <int, String>{}
    ]));
    sb.writeln('}');
    return sb.toString();
  }
}

class AnnotationsDeclaration extends BytecodeDeclaration {
  final ObjectHandle? object;

  AnnotationsDeclaration(this.object);

  void write(BufferedWriter writer) {
    writer.writePackedObject(object);
  }

  factory AnnotationsDeclaration.read(BufferedReader reader) {
    return new AnnotationsDeclaration(reader.readPackedObject());
  }

  @override
  String toString() => object.toString();
}

class _Section {
  int numItems;
  int? offset;
  BufferedWriter? writer;

  _Section(this.numItems, this.writer);

  int get size => writer!.offset;
}

class Component {
  static const int magicValue = 0x44424333; // 'DBC3'
  static const int numSections = 13;
  static const int sectionAlignment = 4;

  //  UInt32 magic, version, numSections x (numItems, offset)
  static const int headerSize = (2 + numSections * 2) * 4;

  late StringTable stringTable;
  late ObjectTable objectTable;
  final List<LibraryDeclaration> libraries = <LibraryDeclaration>[];
  final List<ClassDeclaration> classes = <ClassDeclaration>[];
  final List<Members> members = <Members>[];
  final List<Code> codes = <Code>[];
  final List<SourcePositions> sourcePositions = <SourcePositions>[];
  final List<LineStarts> lineStarts = <LineStarts>[];
  final List<SourceFile> sourceFiles = <SourceFile>[];
  final Map<Uri, SourceFile> uriToSource = <Uri, SourceFile>{};
  final List<LocalVariableTable> localVariables = <LocalVariableTable>[];
  final List<AnnotationsDeclaration> annotations = <AnnotationsDeclaration>[];
  ObjectHandle? dynModuleEntryPoint;

  Component(CoreTypes coreTypes)
      : stringTable = new StringTable(),
        objectTable = new ObjectTable(coreTypes);

  void write(BufferedWriter writer) {
    objectTable.allocateIndexTable();

    // Write sections to their own buffers in reverse order as section may
    // reference data structures from successor sections by offsets.

    final annotationsWriter = new BufferedWriter.fromWriter(writer);
    for (var annot in annotations) {
      writer.linkWriter.put(annot, annotationsWriter.offset);
      annot.write(annotationsWriter);
    }
    BytecodeSizeStatistics.annotationsSize += annotationsWriter.offset;

    final localVariablesWriter = new BufferedWriter.fromWriter(writer);
    for (var lv in localVariables) {
      writer.linkWriter.put(lv, localVariablesWriter.offset);
      lv.write(localVariablesWriter);
    }
    BytecodeSizeStatistics.localVariablesSize += localVariablesWriter.offset;

    final lineStartsWriter = new BufferedWriter.fromWriter(writer);
    for (var ls in lineStarts) {
      writer.linkWriter.put(ls, lineStartsWriter.offset);
      ls.write(lineStartsWriter);
    }
    BytecodeSizeStatistics.lineStartsSize += lineStartsWriter.offset;

    final sourceFilesWriter = new BufferedWriter.fromWriter(writer);
    for (var sf in sourceFiles) {
      writer.linkWriter.put(sf, sourceFilesWriter.offset);
      sf.write(sourceFilesWriter);
    }
    BytecodeSizeStatistics.sourceFilesSize += sourceFilesWriter.offset;

    final sourcePositionsWriter = new BufferedWriter.fromWriter(writer);
    for (var sp in sourcePositions) {
      writer.linkWriter.put(sp, sourcePositionsWriter.offset);
      sp.write(sourcePositionsWriter);
    }
    BytecodeSizeStatistics.sourcePositionsSize += sourcePositionsWriter.offset;

    final codesWriter = new BufferedWriter.fromWriter(writer);
    for (var code in codes) {
      writer.linkWriter.put(code, codesWriter.offset);
      code.write(codesWriter);
    }

    final membersWriter = new BufferedWriter.fromWriter(writer);
    for (var m in members) {
      writer.linkWriter.put(m, membersWriter.offset);
      m.write(membersWriter);
    }

    final classesWriter = new BufferedWriter.fromWriter(writer);
    for (var cls in classes) {
      writer.linkWriter.put(cls, classesWriter.offset);
      cls.write(classesWriter);
    }

    final librariesWriter = new BufferedWriter.fromWriter(writer);
    for (var library in libraries) {
      writer.linkWriter.put(library, librariesWriter.offset);
      library.write(librariesWriter);
    }

    final libraryIndexWriter = new BufferedWriter.fromWriter(writer);
    for (var library in libraries) {
      libraryIndexWriter.writePackedObject(library.importUri);
      libraryIndexWriter.writeLinkOffset(library);
    }
    BytecodeSizeStatistics.librariesSize += libraryIndexWriter.offset;

    BufferedWriter? mainWriter;
    if (dynModuleEntryPoint != null) {
      mainWriter = new BufferedWriter.fromWriter(writer);
      mainWriter.writePackedObject(dynModuleEntryPoint);
    }

    final objectsWriter = new BufferedWriter.fromWriter(writer);
    objectTable.write(objectsWriter);

    final stringsWriter = new BufferedWriter.fromWriter(writer);
    stringTable.write(stringsWriter);

    List<_Section> sections = [
      new _Section(0, stringsWriter),
      new _Section(0, objectsWriter),
      new _Section(0, mainWriter),
      new _Section(libraries.length, libraryIndexWriter),
      new _Section(libraries.length, librariesWriter),
      new _Section(classes.length, classesWriter),
      new _Section(members.length, membersWriter),
      new _Section(codes.length, codesWriter),
      new _Section(sourcePositions.length, sourcePositionsWriter),
      new _Section(sourceFiles.length, sourceFilesWriter),
      new _Section(lineStarts.length, lineStartsWriter),
      new _Section(localVariables.length, localVariablesWriter),
      new _Section(annotations.length, annotationsWriter),
    ];
    assert(sections.length == numSections);

    int offset = headerSize;
    for (var section in sections) {
      if (section.writer != null) {
        section.offset = offset;
        offset += section.size;
      } else {
        section.offset = 0;
      }
    }

    final start = writer.offset;

    writer.writeUInt32(magicValue);
    writer.writeUInt32(bytecodeFormatVersion);
    for (var section in sections) {
      writer.writeUInt32(section.numItems);
      writer.writeUInt32(section.offset!);
    }
    assert(writer.offset - start == headerSize);
    for (var section in sections) {
      final sectionWriter = section.writer;
      if (sectionWriter != null) {
        assert(writer.offset - start == section.offset);
        writer.appendWriter(sectionWriter);
      }
    }

    BytecodeSizeStatistics.componentSize += (writer.offset - start);
  }

  Component.read(BufferedReader reader) {
    final int start = reader.offset;

    final int magic = reader.readUInt32();
    if (magic != magicValue) {
      throw 'Error: unexpected bytecode magic $magic';
    }

    final version = reader.readUInt32();
    if (version != bytecodeFormatVersion) {
      throw 'Error: unexpected bytecode format version $version (expected $bytecodeFormatVersion)';
    }

    reader.readUInt32();
    final stringTableOffset = reader.readUInt32();

    reader.readUInt32();
    final objectTableOffset = reader.readUInt32();

    reader.readUInt32();
    final mainOffset = reader.readUInt32();

    final librariesNum = reader.readUInt32();
    final libraryIndexOffset = reader.readUInt32();

    reader.readUInt32();
    final librariesOffset = reader.readUInt32();

    final classesNum = reader.readUInt32();
    final classesOffset = reader.readUInt32();

    final membersNum = reader.readUInt32();
    final membersOffset = reader.readUInt32();

    final codesNum = reader.readUInt32();
    final codesOffset = reader.readUInt32();

    final sourcePositionsNum = reader.readUInt32();
    final sourcePositionsOffset = reader.readUInt32();

    final sourceFilesNum = reader.readUInt32();
    final sourceFilesOffset = reader.readUInt32();

    final lineStartsNum = reader.readUInt32();
    final lineStartsOffset = reader.readUInt32();

    final localVariablesNum = reader.readUInt32();
    final localVariablesOffset = reader.readUInt32();

    final annotationsNum = reader.readUInt32();
    final annotationsOffset = reader.readUInt32();

    reader.offset = start + stringTableOffset;
    stringTable = new StringTable.read(reader);
    reader.stringReader = stringTable;

    reader.offset = start + objectTableOffset;
    objectTable = new ObjectTable.read(reader);
    reader.objectReader = objectTable;

    // Read sections in the reverse order as section may reference
    // successor sections by offsets.

    final annotationsStart = start + annotationsOffset;
    reader.offset = annotationsStart;
    for (int i = 0; i < annotationsNum; ++i) {
      int offset = reader.offset - annotationsStart;
      AnnotationsDeclaration annot = new AnnotationsDeclaration.read(reader);
      reader.linkReader.setOffset(annot, offset);
      annotations.add(annot);
    }

    final lineStartsStart = start + lineStartsOffset;
    reader.offset = lineStartsStart;
    for (int i = 0; i < lineStartsNum; ++i) {
      int offset = reader.offset - lineStartsStart;
      LineStarts ls = new LineStarts.read(reader);
      reader.linkReader.setOffset(ls, offset);
      lineStarts.add(ls);
    }

    final sourceFilesStart = start + sourceFilesOffset;
    reader.offset = sourceFilesStart;
    for (int i = 0; i < sourceFilesNum; ++i) {
      int offset = reader.offset - sourceFilesStart;
      SourceFile sf = new SourceFile.read(reader);
      reader.linkReader.setOffset(sf, offset);
      sourceFiles.add(sf);
    }

    final sourcePositionsStart = start + sourcePositionsOffset;
    reader.offset = sourcePositionsStart;
    for (int i = 0; i < sourcePositionsNum; ++i) {
      int offset = reader.offset - sourcePositionsStart;
      SourcePositions sp = new SourcePositions.read(reader);
      reader.linkReader.setOffset(sp, offset);
      sourcePositions.add(sp);
    }

    final localVariablesStart = start + localVariablesOffset;
    reader.offset = localVariablesStart;
    for (int i = 0; i < localVariablesNum; ++i) {
      int offset = reader.offset - localVariablesStart;
      LocalVariableTable lv = new LocalVariableTable.read(reader);
      reader.linkReader.setOffset(lv, offset);
      localVariables.add(lv);
    }

    final codesStart = start + codesOffset;
    reader.offset = codesStart;
    for (int i = 0; i < codesNum; ++i) {
      int offset = reader.offset - codesStart;
      Code code = new Code.read(reader);
      reader.linkReader.setOffset(code, offset);
      codes.add(code);
    }

    final membersStart = start + membersOffset;
    reader.offset = membersStart;
    for (int i = 0; i < membersNum; ++i) {
      int offset = reader.offset - membersStart;
      Members m = new Members.read(reader);
      reader.linkReader.setOffset(m, offset);
      members.add(m);
    }

    final classesStart = start + classesOffset;
    reader.offset = classesStart;
    for (int i = 0; i < classesNum; ++i) {
      int offset = reader.offset - classesStart;
      ClassDeclaration cls = new ClassDeclaration.read(reader);
      reader.linkReader.setOffset(cls, offset);
      classes.add(cls);
    }

    final librariesStart = start + librariesOffset;
    reader.offset = librariesStart;
    for (int i = 0; i < librariesNum; ++i) {
      int offset = reader.offset - librariesStart;
      LibraryDeclaration library = new LibraryDeclaration.read(reader);
      reader.linkReader.setOffset(library, offset);
      libraries.add(library);
    }

    final libraryIndexStart = start + libraryIndexOffset;
    reader.offset = libraryIndexStart;
    for (int i = 0; i < librariesNum; ++i) {
      final ObjectHandle importUri = reader.readPackedObject();
      final library = reader.readLinkOffset<LibraryDeclaration>();
      library.importUri = importUri;
    }

    if (mainOffset != 0) {
      reader.offset = start + mainOffset;
      dynModuleEntryPoint = reader.readPackedObject();
    }
  }

  @override
  String toString() {
    final StringBuffer sb = new StringBuffer();
    sb.writeln("Bytecode");
    if (dynModuleEntryPoint != null) {
      sb.writeln("Dynamic Module Entry Point: $dynModuleEntryPoint");
    }
    for (var library in libraries) {
      sb.write(library);
    }
    return sb.toString();
  }
}

void _writeBytecodeInstructions(BufferedWriter writer, Uint8List bytecodes) {
  writer.writePackedUInt30(bytecodes.length);
  writer.appendUint8List(bytecodes);
  BytecodeSizeStatistics.instructionsSize += bytecodes.length;
}

Uint8List _readBytecodeInstructions(BufferedReader reader) {
  int len = reader.readPackedUInt30();
  return reader.readBytesAsUint8List(len);
}
