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

#include "vm/bytecode_reader.h"

#include "vm/globals.h"
#if defined(DART_DYNAMIC_MODULES)

#include "vm/bit_vector.h"
#include "vm/bootstrap.h"
#include "vm/class_finalizer.h"
#include "vm/class_id.h"
#include "vm/closure_functions_cache.h"
#include "vm/code_descriptors.h"
#include "vm/compiler/api/deopt_id.h"
#include "vm/compiler/assembler/disassembler_kbc.h"
#include "vm/constants_kbc.h"
#include "vm/dart_entry.h"
#include "vm/flags.h"
#include "vm/hash.h"
#include "vm/hash_table.h"
#include "vm/longjump.h"
#include "vm/object_store.h"
#include "vm/resolver.h"
#include "vm/reusable_handles.h"
#include "vm/scopes.h"
#include "vm/stack_frame_kbc.h"
#include "vm/symbols.h"
#include "vm/timeline.h"

#define Z (zone_)
#define IG (thread_->isolate_group())

namespace dart {

DEFINE_FLAG(bool, dump_kernel_bytecode, false, "Dump kernel bytecode");

namespace bytecode {

class BytecodeOffsetsMapTraits {
 public:
  static const char* Name() { return "BytecodeOffsetsMapTraits"; }
  static bool ReportStats() { return false; }

  static bool IsMatch(const Object& a, const Object& b) {
    return (a.ptr() == b.ptr());
  }

  static uword Hash(const Object& key) {
    if (key.IsClass()) {
      return Class::Cast(key).id();
    } else if (key.IsFunction()) {
      return Function::Cast(key).Hash();
    } else if (key.IsField()) {
      return Field::Cast(key).Hash();
    } else {
      UNREACHABLE();
    }
  }
};
using BytecodeOffsetsMap = UnorderedHashMap<BytecodeOffsetsMapTraits>;

BytecodeLoader::BytecodeLoader(Thread* thread, const TypedDataBase& binary)
    : thread_(thread),
      binary_(binary),
      bytecode_component_array_(Array::Handle(thread->zone())),
      pending_classes_(GrowableObjectArray::Handle(thread->zone(),
                                                   GrowableObjectArray::New())),
      bytecode_offsets_map_(
          Array::Handle(thread->zone(),
                        HashTables::New<BytecodeOffsetsMap>(16))) {
  ASSERT(thread_ == Thread::Current());
  ASSERT(thread_->bytecode_loader() == nullptr);
  thread_->set_bytecode_loader(this);

  ASSERT(!binary_.IsNull());
  ASSERT(binary_.IsExternalOrExternalView());
}

BytecodeLoader::~BytecodeLoader() {
  ASSERT(thread_->bytecode_loader() == this);
  thread_->set_bytecode_loader(nullptr);
}

FunctionPtr BytecodeLoader::LoadBytecode(bool load_code) {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());

  if (bytecode_component_array_.IsNull()) {
    BytecodeReaderHelper component_reader(thread_, binary_);
    bytecode_component_array_ = component_reader.ReadBytecodeComponent();
  }

  BytecodeComponentData bytecode_component(bytecode_component_array_);
  BytecodeReaderHelper bytecode_reader(thread_, &bytecode_component);
  AlternativeReadingScope alt(&bytecode_reader.reader(),
                              bytecode_component.GetLibraryIndexOffset());
  bytecode_reader.ReadLibraryDeclarations(bytecode_component.GetNumLibraries(),
                                          pending_classes_, load_code);

  if (bytecode_component.GetMainOffset() == 0) {
    return Function::null();
  }

  AlternativeReadingScope alt2(&bytecode_reader.reader(),
                               bytecode_component.GetMainOffset());
  return Function::RawCast(bytecode_reader.ReadObject());
}

void BytecodeLoader::LoadPendingCode() {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  ASSERT(!bytecode_component_array_.IsNull());

  BytecodeComponentData bytecode_component(bytecode_component_array_);
  BytecodeReaderHelper bytecode_reader(thread_, &bytecode_component);
  bytecode_reader.ReadPendingCode(pending_classes_);
}

void BytecodeLoader::SetOffset(const Object& obj, intptr_t offset) {
  BytecodeOffsetsMap map(bytecode_offsets_map_.ptr());
  map.UpdateOrInsert(obj, Smi::Handle(thread_->zone(), Smi::New(offset)));
  bytecode_offsets_map_ = map.Release().ptr();
}

intptr_t BytecodeLoader::GetOffset(const Object& obj) const {
  BytecodeOffsetsMap map(bytecode_offsets_map_.ptr());
  const auto value = map.GetOrNull(obj);
  ASSERT(value != Object::null());
  const intptr_t offset = Smi::Value(Smi::RawCast(value));
  ASSERT(map.Release().ptr() == bytecode_offsets_map_.ptr());
  return offset;
}

bool BytecodeLoader::HasOffset(const Object& obj) const {
  BytecodeOffsetsMap map(bytecode_offsets_map_.ptr());
  const auto value = map.GetOrNull(obj);
  ASSERT(map.Release().ptr() == bytecode_offsets_map_.ptr());
  return value != Object::null();
}

void BytecodeLoader::FindModifiedLibraries(BitVector* modified_libs,
                                           intptr_t* p_num_libraries,
                                           intptr_t* p_num_classes,
                                           intptr_t* p_num_procedures) {
  if (bytecode_component_array_.IsNull()) {
    BytecodeReaderHelper component_reader(thread_, binary_);
    bytecode_component_array_ = component_reader.ReadBytecodeComponent();
  }

  BytecodeComponentData bytecode_component(bytecode_component_array_);
  BytecodeReaderHelper bytecode_reader(thread_, &bytecode_component);
  AlternativeReadingScope alt(&bytecode_reader.reader(),
                              bytecode_component.GetLibraryIndexOffset());

  bytecode_reader.FindModifiedLibraries(modified_libs,
                                        bytecode_component.GetNumLibraries());

  if (p_num_libraries != nullptr) {
    *p_num_libraries = bytecode_component.GetNumLibraries();
  }
  if (p_num_classes != nullptr) {
    *p_num_classes = bytecode_component.GetNumClasses();
  }
  if (p_num_procedures != nullptr) {
    *p_num_procedures = bytecode_component.GetNumCodes();
  }
}

BytecodeReaderHelper::BytecodeReaderHelper(Thread* thread,
                                           const TypedDataBase& typed_data)
    : reader_(typed_data),
      thread_(thread),
      zone_(thread->zone()),
      bytecode_component_(nullptr),
      scoped_function_(Function::Handle(thread->zone())),
      scoped_function_name_(String::Handle(thread->zone())),
      scoped_function_class_(Class::Handle(thread->zone())) {}

BytecodeReaderHelper::BytecodeReaderHelper(
    Thread* thread,
    BytecodeComponentData* bytecode_component)
    : reader_(TypedDataBase::Handle(thread->zone(),
                                    bytecode_component->GetTypedData())),
      thread_(thread),
      zone_(thread->zone()),
      bytecode_component_(bytecode_component),
      scoped_function_(Function::Handle(thread->zone())),
      scoped_function_name_(String::Handle(thread->zone())),
      scoped_function_class_(Class::Handle(thread->zone())) {}

void BytecodeReaderHelper::ReadCode(const Function& function,
                                    intptr_t code_offset) {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  ASSERT(!function.IsImplicitGetterFunction() &&
         !function.IsImplicitSetterFunction());
  if (code_offset == 0) {
    FATAL("Function %s (kind %s) doesn't have bytecode",
          function.ToFullyQualifiedCString(),
          Function::KindToCString(function.kind()));
  }

  AlternativeReadingScope alt(&reader_, code_offset);
  const auto& signature = FunctionType::Handle(Z, function.signature());
  FunctionTypeScope function_type_scope(this, signature);

  const intptr_t flags = reader_.ReadUInt();
  const bool has_exceptions_table =
      (flags & Code::kHasExceptionsTableFlag) != 0;
  const bool has_source_positions =
      (flags & Code::kHasSourcePositionsFlag) != 0;
  const bool has_local_variables = (flags & Code::kHasLocalVariablesFlag) != 0;
  const bool has_nullable_fields = (flags & Code::kHasNullableFieldsFlag) != 0;
  const bool has_closures = (flags & Code::kHasClosuresFlag) != 0;
  const bool has_parameter_flags = (flags & Code::kHasParameterFlagsFlag) != 0;
  const bool has_forwarding_stub_target =
      (flags & Code::kHasForwardingStubTargetFlag) != 0;
  const bool has_default_function_type_args =
      (flags & Code::kHasDefaultFunctionTypeArgsFlag) != 0;

  if (has_parameter_flags) {
    intptr_t num_flags = reader_.ReadUInt();
    for (intptr_t i = 0; i < num_flags; ++i) {
      reader_.ReadUInt();
    }
  }
  if (has_forwarding_stub_target) {
    reader_.ReadUInt();
  }
  if (has_default_function_type_args) {
    reader_.ReadUInt();
  }

  intptr_t num_closures = 0;
  if (has_closures) {
    num_closures = reader_.ReadListLength();
    closures_ = &Array::Handle(Z, Array::New(num_closures));
    for (intptr_t i = 0; i < num_closures; i++) {
      ReadClosureDeclaration(function, i);
    }
  }

  // Create object pool and read pool entries.
  const intptr_t obj_count = reader_.ReadListLength();
  const ObjectPool& pool = ObjectPool::Handle(Z, ObjectPool::New(obj_count));
  ReadConstantPool(function, pool, 0);

  // Read bytecode and attach to function.
  const Bytecode& bytecode = Bytecode::Handle(Z, ReadBytecode(pool));
  bytecode.set_code_offset(code_offset);
  function.AttachBytecode(bytecode);

  ReadExceptionsTable(function, bytecode, has_exceptions_table);

  ReadSourcePositions(bytecode, has_source_positions);

  ReadLocalVariables(bytecode, has_local_variables);

  if (FLAG_dump_kernel_bytecode) {
    KernelBytecodeDisassembler::Disassemble(function);
  }

  // Initialization of fields with null literal is elided from bytecode.
  // Record the corresponding stores if field guards are enabled.
  if (has_nullable_fields) {
    ASSERT(function.IsGenerativeConstructor());
    const intptr_t num_fields = reader_.ReadListLength();
    if (IG->use_field_guards()) {
      Field& field = Field::Handle(Z);
      for (intptr_t i = 0; i < num_fields; i++) {
        field ^= ReadObject();
        field.RecordStore(Object::null_object());
      }
    } else {
      for (intptr_t i = 0; i < num_fields; i++) {
        ReadObject();
      }
    }
  }

  // Read closures.
  if (has_closures) {
    Function& closure = Function::Handle(Z);
    Bytecode& closure_bytecode = Bytecode::Handle(Z);
    for (intptr_t i = 0; i < num_closures; i++) {
      closure ^= closures_->At(i);

      const intptr_t flags = reader_.ReadUInt();
      const bool has_exceptions_table =
          (flags & ClosureCode::kHasExceptionsTableFlag) != 0;
      const bool has_source_positions =
          (flags & ClosureCode::kHasSourcePositionsFlag) != 0;
      const bool has_local_variables =
          (flags & ClosureCode::kHasLocalVariablesFlag) != 0;

      // Read closure bytecode and attach to closure function.
      closure_bytecode = ReadBytecode(pool);
      closure.AttachBytecode(closure_bytecode);

      ReadExceptionsTable(closure, closure_bytecode, has_exceptions_table);

      ReadSourcePositions(closure_bytecode, has_source_positions);

      ReadLocalVariables(closure_bytecode, has_local_variables);

      if (FLAG_dump_kernel_bytecode) {
        KernelBytecodeDisassembler::Disassemble(closure);
      }
    }
  }
}

void BytecodeReaderHelper::ReadClosureDeclaration(const Function& function,
                                                  intptr_t closureIndex) {
  // Closure flags, must be in sync with ClosureDeclaration constants in
  // pkg/dart2bytecode/lib/declarations.dart.
  const int kHasOptionalPositionalParamsFlag = 1 << 0;
  const int kHasOptionalNamedParamsFlag = 1 << 1;
  const int kHasTypeParamsFlag = 1 << 2;
  const int kHasSourcePositionsFlag = 1 << 3;
  const int kIsAsyncFlag = 1 << 4;
  const int kIsAsyncStarFlag = 1 << 5;
  const int kIsSyncStarFlag = 1 << 6;
  const int kIsDebuggableFlag = 1 << 7;
  const int kHasParameterFlagsFlag = 1 << 8;

  const intptr_t flags = reader_.ReadUInt();

  Object& parent = Object::Handle(Z, ReadObject());
  if (!parent.IsFunction()) {
    ASSERT(parent.IsField());
    ASSERT(function.kind() == UntaggedFunction::kFieldInitializer);
    // Closure in a static field initializer, so use current function as parent.
    parent = function.ptr();
  }

  String& name = String::CheckedHandle(Z, ReadObject());
  ASSERT(name.IsSymbol());

  TokenPosition position = TokenPosition::kNoSource;
  TokenPosition end_position = TokenPosition::kNoSource;
  if ((flags & kHasSourcePositionsFlag) != 0) {
    position = reader_.ReadPosition();
    end_position = reader_.ReadPosition();
  }

  const Function& closure = Function::Handle(
      Z, Function::NewClosureFunction(name, Function::Cast(parent), position));

  NOT_IN_PRECOMPILED(closure.set_end_token_pos(end_position));

  if ((flags & kIsSyncStarFlag) != 0) {
    closure.set_modifier(UntaggedFunction::kSyncGen);
    closure.set_is_inlinable(false);
  } else if ((flags & kIsAsyncFlag) != 0) {
    closure.set_modifier(UntaggedFunction::kAsync);
    closure.set_is_inlinable(false);
  } else if ((flags & kIsAsyncStarFlag) != 0) {
    closure.set_modifier(UntaggedFunction::kAsyncGen);
    closure.set_is_inlinable(false);
  }
  closure.set_is_debuggable((flags & kIsDebuggableFlag) != 0);

  closures_->SetAt(closureIndex, closure);

  auto& signature = FunctionType::Handle(Z, closure.signature());
  signature = ReadFunctionSignature(
      signature, closure, (flags & kHasOptionalPositionalParamsFlag) != 0,
      (flags & kHasOptionalNamedParamsFlag) != 0,
      (flags & kHasTypeParamsFlag) != 0,
      /* has_positional_param_names = */ true,
      (flags & kHasParameterFlagsFlag) != 0);

  closure.SetSignature(signature);
}

FunctionTypePtr BytecodeReaderHelper::ReadFunctionSignature(
    const FunctionType& signature,
    const Function& closure_function,
    bool has_optional_positional_params,
    bool has_optional_named_params,
    bool has_type_params,
    bool has_positional_param_names,
    bool has_parameter_flags) {
  FunctionTypeScope function_type_scope(this, signature);

  if (has_type_params) {
    ReadTypeParametersDeclaration(Class::Handle(Z), signature);
  }

  const intptr_t kImplicitClosureParam = 1;
  const intptr_t num_params = kImplicitClosureParam + reader_.ReadUInt();

  intptr_t num_required_params = num_params;
  if (has_optional_positional_params || has_optional_named_params) {
    num_required_params = kImplicitClosureParam + reader_.ReadUInt();
  }

  signature.set_num_implicit_parameters(kImplicitClosureParam);
  signature.set_num_fixed_parameters(num_required_params);
  signature.SetNumOptionalParameters(num_params - num_required_params,
                                     !has_optional_named_params);
  signature.set_parameter_types(
      Array::Handle(Z, Array::New(num_params, Heap::kOld)));
  signature.CreateNameArrayIncludingFlags(Heap::kOld);
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (has_positional_param_names) {
    closure_function.CreateNameArray();
  }
#endif

  intptr_t i = 0;
  signature.SetParameterTypeAt(i, AbstractType::dynamic_type());
  ++i;

  AbstractType& type = AbstractType::Handle(Z);
  String& name = String::Handle(Z);
  for (; i < num_params; ++i) {
    if (has_positional_param_names ||
        (has_optional_named_params && (i >= num_required_params))) {
      name ^= ReadObject();
      if (has_optional_named_params && (i >= num_required_params)) {
        signature.SetParameterNameAt(i, name);
#if !defined(DART_PRECOMPILED_RUNTIME)
      } else {
        closure_function.SetParameterNameAt(i, name);
#endif
      }
    }
    type ^= ReadObject();
    signature.SetParameterTypeAt(i, type);
  }
  if (has_parameter_flags) {
    ASSERT(has_optional_named_params);
    intptr_t num_flags = reader_.ReadUInt();
    for (intptr_t i = 0; i < num_flags; ++i) {
      intptr_t flag = reader_.ReadUInt();
      if ((flag & Parameter::kIsRequiredFlag) != 0) {
        signature.SetIsRequiredAt(num_required_params + i);
      }
    }
  }

  type ^= ReadObject();
  signature.set_result_type(type);

  // Finalize function type.
  return FunctionType::RawCast(
      ClassFinalizer::FinalizeType(signature, ClassFinalizer::kCanonicalize));
}

void BytecodeReaderHelper::ReadTypeParametersDeclaration(
    const Class& parameterized_class,
    const FunctionType& parameterized_signature) {
  ASSERT(parameterized_class.IsNull() != parameterized_signature.IsNull());

  const intptr_t num_type_params = reader_.ReadUInt();
  ASSERT(num_type_params > 0);

  // First setup the type parameters, so if any of the following code uses it
  // (in a recursive way) we're fine.
  //
  // Step a) Create TypeParameters object (without bounds and defaults).
  const TypeParameters& type_parameters =
      TypeParameters::Handle(Z, TypeParameters::New(num_type_params));

  if (!parameterized_class.IsNull()) {
    ASSERT(parameterized_class.type_parameters() == TypeParameters::null());
    parameterized_class.set_type_parameters(type_parameters);
  } else {
    ASSERT(parameterized_signature.type_parameters() == TypeParameters::null());
    parameterized_signature.SetTypeParameters(type_parameters);
  }

  String& name = String::Handle(Z);
  AbstractType& type = AbstractType::Handle(Z);
  for (intptr_t i = 0; i < num_type_params; ++i) {
    name ^= ReadObject();
    ASSERT(name.IsSymbol());
    type_parameters.SetNameAt(i, name);
    // Set bound temporarily to dynamic in order to
    // allow type finalization of type parameter types.
    type_parameters.SetBoundAt(i, Object::dynamic_type());
  }

  // Step b) Fill in the bounds and defaults of all [TypeParameter]s.
  for (intptr_t i = 0; i < num_type_params; ++i) {
    type ^= ReadObject();
    type_parameters.SetBoundAt(i, type);
    type ^= ReadObject();
    type_parameters.SetDefaultAt(i, type);
  }
}

intptr_t BytecodeReaderHelper::ReadConstantPool(const Function& function,
                                                const ObjectPool& pool,
                                                intptr_t start_index) {
  // These enums and the code below reading the constant pool from kernel must
  // be kept in sync with pkg/dart2bytecode/lib/constant_pool.dart.
  enum ConstantPoolTag {
    kInvalid,
    kObjectRef,
    kClass,
    kType,
    kStaticField,
    kInstanceField,
    kTypeArgumentsField,
    kClosureFunction,
    kEndClosureFunctionScope,
    kSubtypeTestCache,
    kEmptyTypeArguments,
    kDirectCall,
    kInterfaceCall,
    kInstantiatedInterfaceCall,
    kDynamicCall,
    kExternalCall,
  };

  Object& obj = Object::Handle(Z);
  Object& elem = Object::Handle(Z);
  Field& field = Field::Handle(Z);
  Class& cls = Class::Handle(Z);
  String& name = String::Handle(Z);
  const intptr_t obj_count = pool.Length();
  for (intptr_t i = start_index; i < obj_count; ++i) {
    const intptr_t tag = reader_.ReadByte();
    switch (tag) {
      case ConstantPoolTag::kInvalid:
        UNREACHABLE();
      case ConstantPoolTag::kStaticField:
        obj = ReadObject();
        ASSERT(obj.IsField());
        break;
      case ConstantPoolTag::kInstanceField:
        field ^= ReadObject();
        // InstanceField constant occupies 2 entries.
        // The first entry is used for field offset.
        obj = Smi::New(field.HostOffset() / kCompressedWordSize);
        pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
                       ObjectPool::Patchability::kNotPatchable,
                       ObjectPool::SnapshotBehavior::kNotSnapshotable);
        pool.SetObjectAt(i, obj);
        ++i;
        ASSERT(i < obj_count);
        // The second entry is used for field object.
        obj = field.ptr();
        break;
      case ConstantPoolTag::kClass:
        obj = ReadObject();
        ASSERT(obj.IsClass());
        break;
      case ConstantPoolTag::kTypeArgumentsField:
        cls ^= ReadObject();
        obj = Smi::New(cls.host_type_arguments_field_offset() /
                       kCompressedWordSize);
        break;
      case ConstantPoolTag::kType:
        obj = ReadObject();
        ASSERT(obj.IsAbstractType());
        break;
      case ConstantPoolTag::kClosureFunction: {
        intptr_t closure_index = reader_.ReadUInt();
        obj = closures_->At(closure_index);
        ASSERT(obj.IsFunction());
        // Set current entry.
        pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
                       ObjectPool::Patchability::kNotPatchable,
                       ObjectPool::SnapshotBehavior::kNotSnapshotable);
        pool.SetObjectAt(i, obj);

        const auto& signature =
            FunctionType::Handle(Z, Function::Cast(obj).signature());
        FunctionTypeScope function_type_scope(this, signature);

        // Read constant pool until corresponding EndClosureFunctionScope.
        i = ReadConstantPool(function, pool, i + 1);

        // Proceed with the rest of entries.
        continue;
      }
      case ConstantPoolTag::kEndClosureFunctionScope: {
        // EndClosureFunctionScope entry is not used and set to null.
        obj = Object::null();
        pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
                       ObjectPool::Patchability::kNotPatchable,
                       ObjectPool::SnapshotBehavior::kNotSnapshotable);
        pool.SetObjectAt(i, obj);
        return i;
      }
      case ConstantPoolTag::kSubtypeTestCache: {
        obj = SubtypeTestCache::New(SubtypeTestCache::kMaxInputs);
      } break;
      case ConstantPoolTag::kEmptyTypeArguments:
        obj = Object::empty_type_arguments().ptr();
        break;
      case ConstantPoolTag::kObjectRef:
        obj = ReadObject();
        break;
      case ConstantPoolTag::kDirectCall: {
        // DirectCall constant occupies 2 entries.
        // The first entry is used for target function.
        obj = ReadObject();
        ASSERT(obj.IsFunction());
        pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
                       ObjectPool::Patchability::kNotPatchable,
                       ObjectPool::SnapshotBehavior::kNotSnapshotable);
        pool.SetObjectAt(i, obj);
        ++i;
        ASSERT(i < obj_count);
        // The second entry is used for arguments descriptor.
        obj = ReadObject();
      } break;
      case ConstantPoolTag::kInterfaceCall: {
        elem = ReadObject();
        ASSERT(elem.IsFunction());
        // InterfaceCall constant occupies 2 entries.
        // The first entry is used for interface target.
        pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
                       ObjectPool::Patchability::kNotPatchable,
                       ObjectPool::SnapshotBehavior::kNotSnapshotable);
        pool.SetObjectAt(i, elem);
        ++i;
        ASSERT(i < obj_count);
        // The second entry is used for arguments descriptor.
        obj = ReadObject();
      } break;
      case ConstantPoolTag::kInstantiatedInterfaceCall: {
        elem = ReadObject();
        ASSERT(elem.IsFunction());
        // InstantiatedInterfaceCall constant occupies 3 entries:
        // 1) Interface target.
        pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
                       ObjectPool::Patchability::kNotPatchable,
                       ObjectPool::SnapshotBehavior::kNotSnapshotable);
        pool.SetObjectAt(i, elem);
        ++i;
        ASSERT(i < obj_count);
        // 2) Arguments descriptor.
        obj = ReadObject();
        pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
                       ObjectPool::Patchability::kNotPatchable,
                       ObjectPool::SnapshotBehavior::kNotSnapshotable);
        pool.SetObjectAt(i, obj);
        ++i;
        ASSERT(i < obj_count);
        // 3) Static receiver type.
        obj = ReadObject();
      } break;
      case ConstantPoolTag::kDynamicCall: {
        name ^= ReadObject();
        ASSERT(name.IsSymbol());
        // Do not mangle ==:
        //   * operator == takes an Object so it is either not checked or
        //     checked at the entry because the parameter is marked covariant,
        //     neither of those cases require a dynamic invocation forwarder
        if (!Field::IsGetterName(name) &&
            (name.ptr() != Symbols::EqualOperator().ptr())) {
          name = Function::CreateDynamicInvocationForwarderName(name);
        }
        // DynamicCall constant occupies 2 entries: selector and arguments
        // descriptor.
        pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
                       ObjectPool::Patchability::kNotPatchable,
                       ObjectPool::SnapshotBehavior::kNotSnapshotable);
        pool.SetObjectAt(i, name);
        ++i;
        ASSERT(i < obj_count);
        // The second entry is used for arguments descriptor.
        obj = ReadObject();
      } break;
      case ConstantPoolTag::kExternalCall: {
        // ExternalCall constant occupies 2 entries:
        // trampoline and native function.
        pool.SetTypeAt(i, ObjectPool::EntryType::kNativeFunction,
                       ObjectPool::Patchability::kNotPatchable,
                       ObjectPool::SnapshotBehavior::kNotSnapshotable);
        pool.SetRawValueAt(i, 0);
        ++i;
        ASSERT(i < obj_count);
        pool.SetTypeAt(i, ObjectPool::EntryType::kNativeFunction,
                       ObjectPool::Patchability::kNotPatchable,
                       ObjectPool::SnapshotBehavior::kNotSnapshotable);
        pool.SetRawValueAt(i, 0);
        continue;
      }
      default:
        UNREACHABLE();
    }
    pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
                   ObjectPool::Patchability::kNotPatchable,
                   ObjectPool::SnapshotBehavior::kNotSnapshotable);
    pool.SetObjectAt(i, obj);
  }

  return obj_count - 1;
}

BytecodePtr BytecodeReaderHelper::ReadBytecode(const ObjectPool& pool) {
  const intptr_t size = reader_.ReadUInt();
  const intptr_t offset = reader_.offset();

  const uint8_t* data = reader_.BufferAt(offset);
  reader_.set_offset(offset + size);

  // Create and return bytecode object.
  return Bytecode::New(reinterpret_cast<uword>(data), size, offset,
                       *(reader_.typed_data()), pool);
}

void BytecodeReaderHelper::ReadExceptionsTable(const Function& function,
                                               const Bytecode& bytecode,
                                               bool has_exceptions_table) {
  const intptr_t try_block_count =
      has_exceptions_table ? reader_.ReadListLength() : 0;
  if (try_block_count > 0) {
    const ObjectPool& pool = ObjectPool::Handle(Z, bytecode.object_pool());
    AbstractType& handler_type = AbstractType::Handle(Z);
    Array& handler_types = Array::Handle(Z);
    DescriptorList* pc_descriptors_list = new (Z) DescriptorList(Z);
    ExceptionHandlerList* exception_handlers_list =
        new (Z) ExceptionHandlerList(function);

    // Encoding of ExceptionsTable is described in
    // pkg/dart2bytecode/lib/exceptions.dart.
    for (intptr_t try_index = 0; try_index < try_block_count; try_index++) {
      intptr_t outer_try_index_plus1 = reader_.ReadUInt();
      intptr_t outer_try_index = outer_try_index_plus1 - 1;
      // PcDescriptors are expressed in terms of return addresses.
      intptr_t start_pc =
          KernelBytecode::BytecodePcToOffset(reader_.ReadUInt(),
                                             /* is_return_address = */ true);
      intptr_t end_pc =
          KernelBytecode::BytecodePcToOffset(reader_.ReadUInt(),
                                             /* is_return_address = */ true);
      intptr_t handler_pc =
          KernelBytecode::BytecodePcToOffset(reader_.ReadUInt(),
                                             /* is_return_address = */ false);
      uint8_t flags = reader_.ReadByte();
      const uint8_t kFlagNeedsStackTrace = 1 << 0;
      const uint8_t kFlagIsSynthetic = 1 << 1;
      const bool needs_stacktrace = (flags & kFlagNeedsStackTrace) != 0;
      const bool is_generated = (flags & kFlagIsSynthetic) != 0;
      intptr_t type_count = reader_.ReadListLength();
      ASSERT(type_count > 0);
      handler_types = Array::New(type_count, Heap::kOld);
      for (intptr_t i = 0; i < type_count; i++) {
        intptr_t type_index = reader_.ReadUInt();
        ASSERT(type_index < pool.Length());
        handler_type ^= pool.ObjectAt(type_index);
        handler_types.SetAt(i, handler_type);
      }
      pc_descriptors_list->AddDescriptor(
          UntaggedPcDescriptors::kOther, start_pc, DeoptId::kNone,
          TokenPosition::kNoSource, try_index,
          UntaggedPcDescriptors::kInvalidYieldIndex);
      pc_descriptors_list->AddDescriptor(
          UntaggedPcDescriptors::kOther, end_pc, DeoptId::kNone,
          TokenPosition::kNoSource, try_index,
          UntaggedPcDescriptors::kInvalidYieldIndex);

      // The exception handler keeps a zone handle of the types array, rather
      // than a raw pointer. Do not share the handle across iterations to avoid
      // clobbering the array.
      exception_handlers_list->AddHandler(
          try_index, outer_try_index, handler_pc, is_generated,
          Array::ZoneHandle(Z, handler_types.ptr()), needs_stacktrace);
    }
    const PcDescriptors& descriptors = PcDescriptors::Handle(
        Z, pc_descriptors_list->FinalizePcDescriptors(bytecode.PayloadStart()));
    bytecode.set_pc_descriptors(descriptors);
    const ExceptionHandlers& handlers = ExceptionHandlers::Handle(
        Z, exception_handlers_list->FinalizeExceptionHandlers(
               bytecode.PayloadStart()));
    bytecode.set_exception_handlers(handlers);
  } else {
    bytecode.set_pc_descriptors(Object::empty_descriptors());
    bytecode.set_exception_handlers(Object::empty_exception_handlers());
  }
}

void BytecodeReaderHelper::ReadSourcePositions(const Bytecode& bytecode,
                                               bool has_source_positions) {
  if (!has_source_positions) {
    return;
  }

  intptr_t offset = reader_.ReadUInt();
  bytecode.set_source_positions_binary_offset(
      bytecode_component_->GetSourcePositionsOffset() + offset);
}

void BytecodeReaderHelper::ReadLocalVariables(const Bytecode& bytecode,
                                              bool has_local_variables) {
  if (!has_local_variables) {
    return;
  }

  const intptr_t offset = reader_.ReadUInt();
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
  bytecode.set_local_variables_binary_offset(
      bytecode_component_->GetLocalVariablesOffset() + offset);
#else
  USE(offset);
#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
}

ArrayPtr BytecodeReaderHelper::ReadBytecodeComponent() {
  AlternativeReadingScope alt(&reader_, 0);

  const intptr_t start_offset = reader_.offset();

  intptr_t magic = reader_.ReadUInt32();
  if (magic != KernelBytecode::kMagicValue) {
    FATAL("Unexpected Dart bytecode magic %" Px, magic);
  }

  const intptr_t version = reader_.ReadUInt32();
  if (version != KernelBytecode::kBytecodeFormatVersion) {
    FATAL("Unsupported Dart bytecode format version %" Pd
          ". "
          "This version of Dart VM supports bytecode format version %" Pd ".",
          version, KernelBytecode::kBytecodeFormatVersion);
  }

  reader_.ReadUInt32();  // Skip stringTable.numItems
  const intptr_t string_table_offset = start_offset + reader_.ReadUInt32();

  reader_.ReadUInt32();  // Skip objectTable.numItems
  const intptr_t object_table_offset = start_offset + reader_.ReadUInt32();

  reader_.ReadUInt32();  // Skip main.numItems
  const intptr_t main_offset = start_offset + reader_.ReadUInt32();

  const intptr_t num_libraries = reader_.ReadUInt32();
  const intptr_t library_index_offset = start_offset + reader_.ReadUInt32();

  reader_.ReadUInt32();  // Skip libraries.numItems
  const intptr_t libraries_offset = start_offset + reader_.ReadUInt32();

  const intptr_t num_classes = reader_.ReadUInt32();
  const intptr_t classes_offset = start_offset + reader_.ReadUInt32();

  reader_.ReadUInt32();  // Skip members.numItems
  const intptr_t members_offset = start_offset + reader_.ReadUInt32();

  const intptr_t num_codes = reader_.ReadUInt32();
  const intptr_t codes_offset = start_offset + reader_.ReadUInt32();

  reader_.ReadUInt32();  // Skip sourcePositions.numItems
  const intptr_t source_positions_offset = start_offset + reader_.ReadUInt32();

  reader_.ReadUInt32();  // Skip sourceFiles.numItems
  const intptr_t source_files_offset = start_offset + reader_.ReadUInt32();

  reader_.ReadUInt32();  // Skip lineStarts.numItems
  const intptr_t line_starts_offset = start_offset + reader_.ReadUInt32();

  reader_.ReadUInt32();  // Skip localVariables.numItems
  const intptr_t local_variables_offset = start_offset + reader_.ReadUInt32();

  reader_.ReadUInt32();  // Skip annotations.numItems
  const intptr_t annotations_offset = start_offset + reader_.ReadUInt32();

  // Read header of string table.
  reader_.set_offset(string_table_offset);
  const intptr_t num_one_byte_strings = reader_.ReadUInt32();
  const intptr_t num_two_byte_strings = reader_.ReadUInt32();
  const intptr_t strings_contents_offset =
      reader_.offset() + (num_one_byte_strings + num_two_byte_strings) * 4;

  // Read header of object table.
  reader_.set_offset(object_table_offset);
  const intptr_t num_objects = reader_.ReadUInt();
  const intptr_t objects_size = reader_.ReadUInt();

  // Skip over contents of objects.
  const intptr_t objects_contents_offset = reader_.offset();
  const intptr_t object_offsets_offset = objects_contents_offset + objects_size;
  reader_.set_offset(object_offsets_offset);

  auto& bytecode_component_array = Array::Handle(
      Z, BytecodeComponentData::New(
             Z, *(reader_.typed_data()), version, num_objects,
             string_table_offset, strings_contents_offset,
             object_offsets_offset, objects_contents_offset, main_offset,
             num_libraries, library_index_offset, libraries_offset, num_classes,
             classes_offset, members_offset, num_codes, codes_offset,
             source_positions_offset, source_files_offset, line_starts_offset,
             local_variables_offset, annotations_offset, Heap::kOld));

  BytecodeComponentData bytecode_component(bytecode_component_array);

  // Read object offsets.
  Smi& offs = Smi::Handle(Z);
  for (intptr_t i = 0; i < num_objects; ++i) {
    offs = Smi::New(reader_.ReadUInt());
    bytecode_component.SetObject(i, offs);
  }

  return bytecode_component_array.ptr();
}

void BytecodeReaderHelper::ResetObjects() {
  reader_.set_offset(bytecode_component_->GetObjectOffsetsOffset());
  const intptr_t num_objects = bytecode_component_->GetNumObjects();

  // Read object offsets.
  Smi& offs = Smi::Handle(Z);
  for (intptr_t i = 0; i < num_objects; ++i) {
    offs = Smi::New(reader_.ReadUInt());
    bytecode_component_->SetObject(i, offs);
  }
}

ObjectPtr BytecodeReaderHelper::ReadObject() {
  uint32_t header = reader_.ReadUInt();
  if ((header & kReferenceBit) != 0) {
    intptr_t index = header >> kIndexShift;
    if (index == 0) {
      return Object::null();
    }
    ObjectPtr obj = bytecode_component_->GetObject(index);
    if (obj->IsHeapObject()) {
      return obj;
    }
    // Object is not loaded yet.
    intptr_t offset = bytecode_component_->GetObjectsContentsOffset() +
                      Smi::Value(Smi::RawCast(obj));
    AlternativeReadingScope alt(&reader_, offset);
    header = reader_.ReadUInt();

    obj = ReadObjectContents(header);
    ASSERT(obj->IsHeapObject());
    {
      REUSABLE_OBJECT_HANDLESCOPE(thread_);
      Object& obj_handle = thread_->ObjectHandle();
      obj_handle = obj;
      bytecode_component_->SetObject(index, obj_handle);
    }
    return obj;
  }

  return ReadObjectContents(header);
}

StringPtr BytecodeReaderHelper::ConstructorName(const Class& cls,
                                                const String& name) {
  GrowableHandlePtrArray<const String> pieces(Z, 3);
  pieces.Add(String::Handle(Z, cls.Name()));
  pieces.Add(Symbols::Dot());
  pieces.Add(name);
  return Symbols::FromConcatAll(thread_, pieces);
}

ObjectPtr BytecodeReaderHelper::ReadObjectContents(uint32_t header) {
  ASSERT(((header & kReferenceBit) == 0));

  // Must be in sync with enum ObjectKind in
  // pkg/dart2bytecode/lib/object_table.dart.
  enum ObjectKind {
    kInvalid,
    kLibrary,
    kScript,
    kClass,
    kMember,
    kClosure,
    kName,
    kConstObject,
    kType,
    kTypeArguments,
    kArgDesc,
  };

  // Member flags, must be in sync with _MemberHandle constants in
  // pkg/dart2bytecode/lib/object_table.dart.
  const intptr_t kFlagIsField = kFlagBit0;
  const intptr_t kFlagIsConstructor = kFlagBit1;

  // ArgDesc flags, must be in sync with _ArgDescHandle constants in
  // pkg/dart2bytecode/lib/object_table.dart.
  const int kFlagHasNamedArgs = kFlagBit0;
  const int kFlagHasTypeArgs = kFlagBit1;

  // Script flags, must be in sync with _ScriptHandle constants in
  // pkg/dart2bytecode/lib/object_table.dart.
  const int kFlagHasSourceFile = kFlagBit0;

  // Name flags, must be in sync with _NameHandle constants in
  // pkg/dart2bytecode/lib/object_table.dart.
  const intptr_t kFlagIsPublic = kFlagBit0;

  const intptr_t kind = (header >> kKindShift) & kKindMask;
  const intptr_t flags = header & kFlagsMask;

  switch (kind) {
    case kInvalid:
      UNREACHABLE();
      break;
    case kLibrary: {
      String& uri = String::CheckedHandle(Z, ReadObject());
      LibraryPtr library = Library::LookupLibrary(thread_, uri);
      if (library == Library::null()) {
        FATAL("Unable to find library %s", uri.ToCString());
      }
      return library;
    }
    case kClass: {
      const Library& library = Library::CheckedHandle(Z, ReadObject());
      const String& class_name = String::CheckedHandle(Z, ReadObject());
      if (class_name.ptr() == Symbols::Empty().ptr()) {
        NoSafepointScope no_safepoint_scope(thread_);
        ClassPtr cls = library.toplevel_class();
        if (cls == Class::null()) {
          FATAL("Unable to find toplevel class %s", library.ToCString());
        }
        return cls;
      }
      ClassPtr cls = library.LookupClassAllowPrivate(class_name);
      if (cls == Class::null()) {
        FATAL("Unable to find class %s in %s", class_name.ToCString(),
              library.ToCString());
      }
      return cls;
    }
    case kMember: {
      const Class& cls = Class::CheckedHandle(Z, ReadObject());
      String& name = String::CheckedHandle(Z, ReadObject());
      if ((flags & kFlagIsField) != 0) {
        FieldPtr field = cls.LookupField(name);
        if (field == Field::null()) {
          FATAL("Unable to find field %s in %s", name.ToCString(),
                cls.ToCString());
        }
        return field;
      } else {
        if ((flags & kFlagIsConstructor) != 0) {
          name = ConstructorName(cls, name);
        }
        ASSERT(!name.IsNull() && name.IsSymbol());
        if (name.ptr() == scoped_function_name_.ptr() &&
            cls.ptr() == scoped_function_class_.ptr()) {
          return scoped_function_.ptr();
        }
        FunctionPtr function = Function::null();
        if ((flags & kFlagIsConstructor) != 0) {
          if (cls.EnsureIsAllocateFinalized(thread_) == Error::null()) {
            function = Resolver::ResolveFunction(Z, cls, name);
          }
        } else {
          if (cls.EnsureIsFinalized(thread_) == Error::null()) {
            function = Resolver::ResolveFunction(Z, cls, name);
          }
        }
        if (function == Function::null()) {
          // When requesting a getter, also return method extractors.
          if (Field::IsGetterName(name)) {
            String& method_name =
                String::Handle(Z, Field::NameFromGetter(name));
            function = Resolver::ResolveFunction(Z, cls, method_name);
            if (function != Function::null()) {
              function = Function::Handle(Z, function).GetMethodExtractor(name);
              if (function != Function::null()) {
                return function;
              }
            }
          }
          FATAL("Unable to find function %s in %s", name.ToCString(),
                cls.ToCString());
        }
        return function;
      }
    }
    case kClosure: {
      ReadObject();  // Skip enclosing member.
      const intptr_t closure_index = reader_.ReadUInt();
      return closures_->At(closure_index);
    }
    case kName: {
      if ((flags & kFlagIsPublic) == 0) {
        const Library& library = Library::CheckedHandle(Z, ReadObject());
        ASSERT(!library.IsNull());
        auto& name = String::Handle(Z, ReadString(/* is_canonical = */ false));
        name = library.PrivateName(name);
        return name.ptr();
      }
      return ReadString();
    }
    case kTypeArguments: {
      return ReadTypeArguments();
    }
    case kConstObject: {
      const intptr_t tag = flags / kFlagBit0;
      return ReadConstObject(tag);
    }
    case kArgDesc: {
      const intptr_t num_arguments = reader_.ReadUInt();
      const intptr_t num_type_args =
          ((flags & kFlagHasTypeArgs) != 0) ? reader_.ReadUInt() : 0;
      if ((flags & kFlagHasNamedArgs) == 0) {
        return ArgumentsDescriptor::NewBoxed(num_type_args, num_arguments);
      } else {
        const intptr_t num_arg_names = reader_.ReadListLength();
        const Array& array = Array::Handle(Z, Array::New(num_arg_names));
        String& name = String::Handle(Z);
        for (intptr_t i = 0; i < num_arg_names; ++i) {
          name ^= ReadObject();
          array.SetAt(i, name);
        }
        return ArgumentsDescriptor::NewBoxed(num_type_args, num_arguments,
                                             array);
      }
    }
    case kScript: {
      const String& uri = String::CheckedHandle(Z, ReadObject());
      if ((flags & kFlagHasSourceFile) != 0) {
        return ReadSourceFile(uri, bytecode_component_->GetSourceFilesOffset() +
                                       reader_.ReadUInt());
      }
      return Script::New(uri, Object::null_string());
    }
    case kType: {
      const intptr_t tag = (flags & kTagMask) / kFlagBit0;
      const Nullability nullability = ((flags & kFlagIsNullable) != 0)
                                          ? Nullability::kNullable
                                          : Nullability::kNonNullable;
      return ReadType(tag, nullability);
    }
    default:
      UNREACHABLE();
  }

  return Object::null();
}

ObjectPtr BytecodeReaderHelper::ReadConstObject(intptr_t tag) {
  // Must be in sync with enum ConstTag in
  // pkg/dart2bytecode/lib/object_table.dart.
  enum ConstTag {
    kInvalid,
    kInt,
    kDouble,
    kBool,
    kString,
    kSymbol,
    kInstance,
    kList,
    kMap,
    kSet,
    kRecord,
    kTearOff,
    kTearOffInstantiation,
  };

  switch (tag) {
    case kInvalid:
      UNREACHABLE();
      break;
    case kInstance: {
      const Type& type = Type::CheckedHandle(Z, ReadObject());
      const Class& cls = Class::Handle(Z, type.type_class());
      const Instance& obj = Instance::Handle(Z, Instance::New(cls, Heap::kOld));
      if (cls.NumTypeArguments() > 0) {
        auto& type_args = TypeArguments::Handle(Z, type.arguments());
        type_args = cls.GetInstanceTypeArguments(thread_, type_args);
        obj.SetTypeArguments(type_args);
      } else {
        ASSERT(type.arguments() == TypeArguments::null());
      }
      const intptr_t num_fields = reader_.ReadUInt();
      Field& field = Field::Handle(Z);
      Object& value = Object::Handle(Z);
      for (intptr_t i = 0; i < num_fields; ++i) {
        field ^= ReadObject();
        value = ReadObject();
        obj.SetField(field, value);
      }
      return Canonicalize(obj);
    }
    case kInt: {
      const int64_t value = reader_.ReadSLEB128AsInt64();
      if (Smi::IsValid(value)) {
        return Smi::New(static_cast<intptr_t>(value));
      }
      const Integer& obj = Integer::Handle(Z, Integer::New(value, Heap::kOld));
      return Canonicalize(obj);
    }
    case kDouble: {
      const int64_t bits = reader_.ReadSLEB128AsInt64();
      double value = bit_cast<double, int64_t>(bits);
      const Double& obj = Double::Handle(Z, Double::New(value, Heap::kOld));
      return Canonicalize(obj);
    }
    case kList: {
      const AbstractType& elem_type =
          AbstractType::CheckedHandle(Z, ReadObject());
      const intptr_t length = reader_.ReadUInt();
      const Array& array = Array::Handle(Z, Array::New(length, elem_type));
      Object& value = Object::Handle(Z);
      for (intptr_t i = 0; i < length; ++i) {
        value = ReadObject();
        array.SetAt(i, value);
      }
      array.MakeImmutable();
      return Canonicalize(array);
    }
    case kTearOff: {
      Object& obj = Object::Handle(Z, ReadObject());
      ASSERT(obj.IsFunction());
      obj = Function::Cast(obj).ImplicitClosureFunction();
      ASSERT(obj.IsFunction());
      obj = Function::Cast(obj).ImplicitStaticClosure();
      ASSERT(obj.IsInstance());
      return Canonicalize(Instance::Cast(obj));
    }
    case kBool: {
      bool is_true = reader_.ReadByte() != 0;
      return is_true ? Bool::True().ptr() : Bool::False().ptr();
    }
    case kSymbol: {
      const String& name = String::CheckedHandle(Z, ReadObject());
      ASSERT(name.IsSymbol());
      const Library& library = Library::Handle(Z, Library::InternalLibrary());
      ASSERT(!library.IsNull());
      const Class& cls =
          Class::Handle(Z, library.LookupClass(Symbols::Symbol()));
      ASSERT(!cls.IsNull());
      const Field& field = Field::Handle(
          Z, cls.LookupInstanceFieldAllowPrivate(Symbols::_name()));
      ASSERT(!field.IsNull());
      const Instance& obj = Instance::Handle(Z, Instance::New(cls, Heap::kOld));
      obj.SetField(field, name);
      return Canonicalize(obj);
    }
    case kTearOffInstantiation: {
      Closure& closure = Closure::CheckedHandle(Z, ReadObject());
      const TypeArguments& type_args =
          TypeArguments::CheckedHandle(Z, ReadObject());
      closure = Closure::New(
          TypeArguments::Handle(Z, closure.instantiator_type_arguments()),
          TypeArguments::Handle(Z, closure.function_type_arguments()),
          type_args, Function::Handle(Z, closure.function()),
          Object::Handle(Z, closure.RawContext()), Heap::kOld);
      return Canonicalize(closure);
    }
    case kString:
      return ReadString();
    case kMap: {
      const auto& map_type = Type::CheckedHandle(Z, ReadObject());
      const intptr_t used_data = reader_.ReadUInt();

      const auto& map_class =
          Class::Handle(Z, IG->object_store()->const_map_impl_class());
      ASSERT(!map_class.IsNull());
      ASSERT(map_class.is_finalized());

      auto& type_arguments = TypeArguments::Handle(Z, map_type.arguments());
      type_arguments =
          map_class.GetInstanceTypeArguments(thread_, type_arguments);

      const auto& map = Map::Handle(Z, ConstMap::NewUninitialized(Heap::kOld));
      ASSERT_EQUAL(map.GetClassId(), kConstMapCid);
      map.SetTypeArguments(type_arguments);
      map.set_used_data(used_data);

      const auto& data = Array::Handle(Z, Array::New(used_data));
      map.set_data(data);
      map.set_deleted_keys(0);
      map.ComputeAndSetHashMask();

      Object& value = Object::Handle(Z);
      for (intptr_t i = 0; i < used_data; ++i) {
        value = ReadObject();
        data.SetAt(i, value);
      }
      return Canonicalize(map);
    }
    case kSet: {
      const AbstractType& elem_type =
          AbstractType::CheckedHandle(Z, ReadObject());

      const auto& set_class =
          Class::Handle(Z, IG->object_store()->const_set_impl_class());
      ASSERT(!set_class.IsNull());
      ASSERT(set_class.is_finalized());

      auto& type_arguments =
          TypeArguments::Handle(Z, TypeArguments::New(1, Heap::kOld));
      type_arguments.SetTypeAt(0, elem_type);
      type_arguments =
          set_class.GetInstanceTypeArguments(thread_, type_arguments);

      const auto& set = Set::Handle(Z, ConstSet::NewUninitialized(Heap::kOld));
      ASSERT_EQUAL(set.GetClassId(), kConstSetCid);
      set.SetTypeArguments(type_arguments);

      const intptr_t length = reader_.ReadUInt();
      set.set_used_data(length);

      const auto& data = Array::Handle(Z, Array::New(length));
      set.set_data(data);
      set.set_deleted_keys(0);
      set.ComputeAndSetHashMask();

      Object& value = Object::Handle(Z);
      for (intptr_t i = 0; i < length; ++i) {
        value = ReadObject();
        data.SetAt(i, value);
      }
      return Canonicalize(set);
    }
    case kRecord: {
      const RecordType& record_type =
          RecordType::CheckedHandle(Z, ReadObject());
      const intptr_t num_fields = reader_.ReadUInt();
      ASSERT(num_fields == record_type.NumFields());
      const RecordShape shape = record_type.shape();
      const auto& record = Record::Handle(Z, Record::New(shape));
      Object& value = Object::Handle(Z);
      for (intptr_t i = 0; i < num_fields; ++i) {
        value = ReadObject();
        record.SetFieldAt(i, value);
      }
      return Canonicalize(record);
    }
    default:
      UNREACHABLE();
  }
  return Object::null();
}

ObjectPtr BytecodeReaderHelper::ReadType(intptr_t tag,
                                         Nullability nullability) {
  // Must be in sync with enum TypeTag in
  // pkg/dart2bytecode/lib/object_table.dart.
  enum TypeTag {
    kInvalid,
    kDynamic,
    kVoid,
    kNull,
    kNever,
    kSimpleType,
    kGenericType,
    kTypeParameter,
    kFunctionType,
    kRecordType,
  };

  // FunctionType flags, must be in sync with _FunctionTypeHandle constants in
  // pkg/dart2bytecode/lib/object_table.dart.
  const int kFlagHasOptionalPositionalParams = 1 << 0;
  const int kFlagHasOptionalNamedParams = 1 << 1;
  const int kFlagHasTypeParams = 1 << 2;
  const int kFlagHasEnclosingTypeParameters = 1 << 3;
  const int kFlagHasParameterFlags = 1 << 4;

  switch (tag) {
    case kInvalid:
      UNREACHABLE();
      break;
    case kDynamic:
      return Type::DynamicType();
    case kVoid:
      return Type::VoidType();
    case kNull:
      return Type::NullType();
    case kNever:
      return Type::Handle(Z, Type::NeverType())
          .ToNullability(nullability, Heap::kOld);
    case kSimpleType: {
      const Class& cls = Class::CheckedHandle(Z, ReadObject());
      if (!cls.is_declaration_loaded()) {
        LoadReferencedClass(cls);
      }
      const Type& type = Type::Handle(Z, cls.DeclarationType());
      return type.ToNullability(nullability, Heap::kOld);
    }
    case kTypeParameter: {
      Object& parent = Object::Handle(Z, ReadObject());
      const intptr_t index_in_parent = reader_.ReadUInt();
      auto& type = TypeParameter::Handle(Z);
      if (parent.IsClass()) {
        type =
            Class::Cast(parent).TypeParameterAt(index_in_parent, nullability);
      } else if (parent.IsFunction()) {
        if (Function::Cast(parent).IsFactory()) {
          // For factory constructors VM uses type parameters of a class
          // instead of constructor's type parameters.
          parent = Function::Cast(parent).Owner();
          type =
              Class::Cast(parent).TypeParameterAt(index_in_parent, nullability);
        } else {
          type = Function::Cast(parent).TypeParameterAt(index_in_parent,
                                                        nullability);
        }
      } else if (parent.IsNull()) {
        ASSERT(!enclosing_function_types_.is_empty());
        for (intptr_t i = enclosing_function_types_.length() - 1; i >= 0; --i) {
          parent = enclosing_function_types_[i]->ptr();
          ASSERT(index_in_parent <
                 FunctionType::Cast(parent).NumTypeArguments());
          if (index_in_parent >=
              FunctionType::Cast(parent).NumParentTypeArguments()) {
            break;
          }
        }
        type = FunctionType::Cast(parent).TypeParameterAt(
            index_in_parent -
                FunctionType::Cast(parent).NumParentTypeArguments(),
            nullability);
      } else {
        UNREACHABLE();
      }
      return ClassFinalizer::FinalizeType(type, ClassFinalizer::kCanonicalize);
    }
    case kGenericType: {
      const Class& cls = Class::CheckedHandle(Z, ReadObject());
      if (!cls.is_declaration_loaded()) {
        LoadReferencedClass(cls);
      }
      const TypeArguments& type_arguments =
          TypeArguments::CheckedHandle(Z, ReadObject());
      const Type& type =
          Type::Handle(Z, Type::New(cls, type_arguments, nullability));
      type.SetIsFinalized();
      return type.Canonicalize(thread_);
    }
    case kFunctionType: {
      const intptr_t flags = reader_.ReadUInt();
      intptr_t num_parent_type_args = 0;
      if ((flags & kFlagHasEnclosingTypeParameters) != 0) {
        num_parent_type_args = reader_.ReadUInt();
        ASSERT(num_parent_type_args > 0);
        ASSERT(!enclosing_function_types_.is_empty());
        ASSERT(num_parent_type_args ==
               enclosing_function_types_.Last()->NumTypeArguments());
      }
      auto& signature_type = FunctionType::Handle(
          Z, FunctionType::New(num_parent_type_args, nullability));
      // TODO(alexmarkov): skip type finalization
      return ReadFunctionSignature(
          signature_type, Function::null_function(),
          (flags & kFlagHasOptionalPositionalParams) != 0,
          (flags & kFlagHasOptionalNamedParams) != 0,
          (flags & kFlagHasTypeParams) != 0,
          /* has_positional_param_names = */ false,
          (flags & kFlagHasParameterFlags) != 0);
    }
    case kRecordType: {
      const intptr_t num_positional = reader_.ReadUInt();
      const intptr_t num_named = reader_.ReadUInt();

      const intptr_t num_fields = num_positional + num_named;
      const Array& field_types =
          Array::Handle(Z, Array::New(num_fields, Heap::kOld));
      const Array& field_names =
          (num_named == 0)
              ? Object::empty_array()
              : Array::Handle(Z, Array::New(num_named, Heap::kOld));
      AbstractType& type = AbstractType::Handle(Z);

      intptr_t pos = 0;
      for (intptr_t i = 0; i < num_positional; ++i) {
        type ^= ReadObject();
        field_types.SetAt(pos++, type);
      }

      if (num_named > 0) {
        String& name = String::Handle(Z);
        for (intptr_t i = 0; i < num_named; ++i) {
          name ^= ReadObject();
          field_names.SetAt(i, name);
          type ^= ReadObject();
          field_types.SetAt(pos++, type);
        }
        field_names.MakeImmutable();
      }

      const RecordShape shape =
          RecordShape::Register(thread_, num_fields, field_names);

      type = RecordType::New(shape, field_types, nullability);
      type.SetIsFinalized();
      return type.Canonicalize(thread_);
    }

      UNIMPLEMENTED();
    default:
      UNREACHABLE();
  }
  return Object::null();
}

StringPtr BytecodeReaderHelper::ReadString(bool is_canonical) {
  const int kFlagTwoByteString = 1;
  const int kHeaderFields = 2;
  const int kUInt32Size = 4;

  uint32_t ref = reader_.ReadUInt();
  const bool isOneByteString = (ref & kFlagTwoByteString) == 0;
  intptr_t index = ref >> 1;

  if (!isOneByteString) {
    const uint32_t num_one_byte_strings =
        reader_.ReadUInt32At(bytecode_component_->GetStringsHeaderOffset());
    index += num_one_byte_strings;
  }

  AlternativeReadingScope alt(&reader_,
                              bytecode_component_->GetStringsHeaderOffset() +
                                  (kHeaderFields + index - 1) * kUInt32Size);
  intptr_t start_offs = reader_.ReadUInt32();
  intptr_t end_offs = reader_.ReadUInt32();
  if (index == 0) {
    // For the 0-th string we read a header field instead of end offset of
    // the previous string.
    start_offs = 0;
  }

  // Bytecode strings reside in ExternalTypedData which is not movable by GC,
  // so it is OK to take a direct pointer to string characters even if
  // symbol allocation triggers GC.
  const uint8_t* data = reader_.BufferAt(
      bytecode_component_->GetStringsContentsOffset() + start_offs);

  if (is_canonical) {
    if (isOneByteString) {
      return Symbols::FromLatin1(thread_, data, end_offs - start_offs);
    } else {
      return Symbols::FromUTF16(thread_,
                                reinterpret_cast<const uint16_t*>(data),
                                (end_offs - start_offs) >> 1);
    }
  } else {
    if (isOneByteString) {
      return String::FromLatin1(data, end_offs - start_offs, Heap::kOld);
    } else {
      return String::FromUTF16(reinterpret_cast<const uint16_t*>(data),
                               (end_offs - start_offs) >> 1, Heap::kOld);
    }
  }
}

TypedDataPtr BytecodeReaderHelper::ReadLineStartsData(
    intptr_t line_starts_offset) {
  AlternativeReadingScope alt(&reader_, line_starts_offset);

  const intptr_t num_line_starts = reader_.ReadUInt();

  // Choose representation between Uint16 and Uint32 typed data.
  intptr_t max_start = 0;
  {
    AlternativeReadingScope alt2(&reader_, reader_.offset());
    for (intptr_t i = 0; i < num_line_starts; ++i) {
      const intptr_t delta = reader_.ReadUInt();
      max_start += delta;
    }
  }

  const intptr_t cid = (max_start <= kMaxUint16) ? kTypedDataUint16ArrayCid
                                                 : kTypedDataUint32ArrayCid;
  const TypedData& line_starts_data =
      TypedData::Handle(Z, TypedData::New(cid, num_line_starts, Heap::kOld));

  intptr_t current_start = 0;
  for (intptr_t i = 0; i < num_line_starts; ++i) {
    const intptr_t delta = reader_.ReadUInt();
    current_start += delta;
    if (cid == kTypedDataUint16ArrayCid) {
      line_starts_data.SetUint16(i << 1, static_cast<uint16_t>(current_start));
    } else {
      line_starts_data.SetUint32(i << 2, current_start);
    }
  }

  return line_starts_data.ptr();
}

ScriptPtr BytecodeReaderHelper::ReadSourceFile(const String& uri,
                                               intptr_t offset) {
  // SourceFile flags, must be in sync with SourceFile constants in
  // pkg/dart2bytecode/lib/declarations.dart.
  const int kHasLineStartsFlag = 1 << 0;
  const int kHasSourceFlag = 1 << 1;

  AlternativeReadingScope alt(&reader_, offset);

  const intptr_t flags = reader_.ReadUInt();
  const String& import_uri = String::CheckedHandle(Z, ReadObject());

  TypedData& line_starts = TypedData::Handle(Z);
  if ((flags & kHasLineStartsFlag) != 0) {
    const intptr_t line_starts_offset =
        bytecode_component_->GetLineStartsOffset() + reader_.ReadUInt();
    line_starts = ReadLineStartsData(line_starts_offset);
  }

  String& source = String::Handle(Z);
  if ((flags & kHasSourceFlag) != 0) {
    source = ReadString(/* is_canonical = */ false);
  }

  const Script& script =
      Script::Handle(Z, Script::New(import_uri, uri, source));
  script.set_line_starts(line_starts);

  return script.ptr();
}

TypeArgumentsPtr BytecodeReaderHelper::ReadTypeArguments() {
  const intptr_t length = reader_.ReadUInt();
  TypeArguments& type_arguments =
      TypeArguments::ZoneHandle(Z, TypeArguments::New(length));
  AbstractType& type = AbstractType::Handle(Z);
  for (intptr_t i = 0; i < length; ++i) {
    type ^= ReadObject();
    type_arguments.SetTypeAt(i, type);
  }
  return type_arguments.Canonicalize(thread_);
}

void BytecodeReaderHelper::ReadAnnotations(const Class& cls,
                                           const Object& declaration,
                                           bool has_pragma) {
  const intptr_t annotations_offset =
      reader_.ReadUInt() + bytecode_component_->GetAnnotationsOffset();
  ASSERT(annotations_offset > 0);

#if !defined(DART_PRECOMPILED_RUNTIME)
  if (FLAG_enable_mirrors || has_pragma) {
    AlternativeReadingScope alt(&reader_, annotations_offset);
    const auto& metadata = Object::Handle(Z, ReadObject());
    ASSERT(metadata.IsArray());
    const auto& library = Library::Handle(Z, cls.library());
    library.AddMetadata(declaration, metadata);
  }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
}

void BytecodeReaderHelper::ReadMembers(const Class& cls, bool discard_fields) {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  ASSERT(cls.is_type_finalized());
  ASSERT(!cls.is_loaded());

  const intptr_t num_functions = reader_.ReadUInt();
  functions_ = &Array::Handle(Z, Array::New(num_functions, Heap::kOld));
  function_index_ = 0;

  ReadFieldDeclarations(cls, discard_fields);
  ReadFunctionDeclarations(cls);

  ASSERT(!cls.is_loaded());
  cls.set_is_loaded(true);
}

void BytecodeReaderHelper::ReadFieldDeclarations(const Class& cls,
                                                 bool discard_fields) {
  // Field flags, must be in sync with FieldDeclaration constants in
  // pkg/dart2bytecode/lib/declarations.dart.
  const int kIsStaticFlag = 1 << 0;
  const int kIsConstFlag = 1 << 1;
  const int kIsFinalFlag = 1 << 2;
  const int kIsLateFlag = 1 << 3;
  const int kIsCovariantFlag = 1 << 4;
  const int kIsCovariantByClassFlag = 1 << 5;
  const int kIsExtensionMemberFlag = 1 << 6;
  const int kIsReflectableFlag = 1 << 7;
  const int kHasGetterFlag = 1 << 8;
  const int kHasSetterFlag = 1 << 9;
  const int kHasInitializerFlag = 1 << 10;
  const int kHasNontrivialInitializerFlag = 1 << 11;
  const int kHasInitializerCodeFlag = 1 << 12;
  const int kHasSourcePositionsFlag = 1 << 13;
  const int kHasAnnotationsFlag = 1 << 14;
  const int kHasPragmaFlag = 1 << 15;
  const int kHasCustomScriptFlag = 1 << 16;

  const int num_fields = reader_.ReadListLength();
  if ((num_fields == 0) && !cls.is_enum_class()) {
    return;
  }
  const Array& fields = Array::Handle(
      Z, Array::New(num_fields + (cls.is_enum_class() ? 1 : 0), Heap::kOld));
  String& name = String::Handle(Z);
  Object& script_class = Object::Handle(Z);
  AbstractType& type = AbstractType::Handle(Z);
  Field& field = Field::Handle(Z);
  Object& value = Object::Handle(Z);
  Function& function = Function::Handle(Z);

  for (intptr_t i = 0; i < num_fields; ++i) {
    intptr_t flags = reader_.ReadUInt();

    const bool is_static = (flags & kIsStaticFlag) != 0;
    const bool is_final = (flags & kIsFinalFlag) != 0;
    const bool is_const = (flags & kIsConstFlag) != 0;
    const bool is_late = (flags & kIsLateFlag) != 0;
    const bool has_nontrivial_initializer =
        (flags & kHasNontrivialInitializerFlag) != 0;
    const bool has_pragma = (flags & kHasPragmaFlag) != 0;
    const bool is_extension_member = (flags & kIsExtensionMemberFlag) != 0;
    const bool has_initializer = (flags & kHasInitializerFlag) != 0;

    name ^= ReadObject();
    type ^= ReadObject();

    if ((flags & kHasCustomScriptFlag) != 0) {
      Script& script = Script::CheckedHandle(Z, ReadObject());
      script_class = GetPatchClass(cls, script);
    } else {
      script_class = cls.ptr();
    }

    TokenPosition position = TokenPosition::kNoSource;
    TokenPosition end_position = TokenPosition::kNoSource;
    if ((flags & kHasSourcePositionsFlag) != 0) {
      position = reader_.ReadPosition();
      end_position = reader_.ReadPosition();
    }

    field = Field::New(name, is_static, is_final, is_const,
                       (flags & kIsReflectableFlag) != 0, is_late, script_class,
                       type, position, end_position);

    field.set_is_unboxed(false);
    field.set_has_pragma(has_pragma);
    field.set_is_covariant((flags & kIsCovariantFlag) != 0);
    field.set_is_generic_covariant_impl((flags & kIsCovariantByClassFlag) != 0);
    field.set_has_nontrivial_initializer(has_nontrivial_initializer);
    field.set_is_extension_member(is_extension_member);
    field.set_has_initializer(has_initializer);

    if (!has_nontrivial_initializer) {
      value = ReadObject();
      if (is_static) {
        if (field.is_late() && !has_initializer) {
          value = Object::sentinel().ptr();
        }
      } else {
        // Null-initialized instance fields are tracked separately for each
        // constructor (see handling of kHasNullableFieldsFlag).
        if (!value.IsNull()) {
          field.RecordStore(value);
        }
      }
    }

    if ((flags & kHasInitializerCodeFlag) != 0) {
      const intptr_t code_offset = reader_.ReadUInt();
      BytecodeLoader* loader = thread_->bytecode_loader();
      ASSERT(loader != nullptr);
      loader->SetOffset(field,
                        code_offset + bytecode_component_->GetCodesOffset());
      if (is_static) {
        value = Object::sentinel().ptr();
      }
    }

    if ((flags & kHasGetterFlag) != 0) {
      name ^= ReadObject();
      const auto& signature = FunctionType::Handle(Z, FunctionType::New());
      function =
          Function::New(signature, name,
                        is_static ? UntaggedFunction::kImplicitStaticGetter
                                  : UntaggedFunction::kImplicitGetter,
                        is_static, is_const,
                        false,  // is_abstract
                        false,  // is_external
                        false,  // is_native
                        script_class, position);
      NOT_IN_PRECOMPILED(function.set_end_token_pos(end_position));
      signature.set_result_type(type);
      function.set_is_debuggable(false);
      function.set_accessor_field(field);
      function.set_is_extension_member(is_extension_member);
      SetupFieldAccessorFunction(cls, function, type);
      if (is_static) {
        function.AttachBytecode(Object::implicit_static_getter_bytecode());
      } else {
        function.AttachBytecode(Object::implicit_getter_bytecode());
      }
      functions_->SetAt(function_index_++, function);
    }

    if ((flags & kHasSetterFlag) != 0) {
      ASSERT(is_late || ((!is_static) && (!is_final)));
      ASSERT(!is_const);
      name ^= ReadObject();
      const auto& signature = FunctionType::Handle(Z, FunctionType::New());
      function = Function::New(signature, name,
                               UntaggedFunction::kImplicitSetter, is_static,
                               false,  // is_const
                               false,  // is_abstract
                               false,  // is_external
                               false,  // is_native
                               script_class, position);
      NOT_IN_PRECOMPILED(function.set_end_token_pos(end_position));
      signature.set_result_type(Object::void_type());
      function.set_is_debuggable(false);
      function.set_accessor_field(field);
      function.set_is_extension_member(is_extension_member);
      SetupFieldAccessorFunction(cls, function, type);
      if (is_static) {
        function.AttachBytecode(Object::implicit_static_setter_bytecode());
      } else {
        function.AttachBytecode(Object::implicit_setter_bytecode());
      }
      functions_->SetAt(function_index_++, function);
    }

    if ((flags & kHasAnnotationsFlag) != 0) {
      ReadAnnotations(cls, field, has_pragma);
    }

    if (field.is_static()) {
      IG->RegisterStaticField(field, value);
    }

    fields.SetAt(i, field);
  }

  if (cls.is_enum_class()) {
    // Add static field 'const _deleted_enum_sentinel'.
    field = Field::New(Symbols::_DeletedEnumSentinel(),
                       /* is_static = */ true,
                       /* is_final = */ true,
                       /* is_const = */ true,
                       /* is_reflectable = */ false,
                       /* is_late = */ false, cls, Object::dynamic_type(),
                       TokenPosition::kNoSource, TokenPosition::kNoSource);
    IG->RegisterStaticField(field, Object::null_object());
    fields.SetAt(num_fields, field);
  }

  if (!discard_fields) {
    cls.SetFields(fields);
  }

  if (cls.IsTopLevel()) {
    const Library& library = Library::Handle(Z, cls.library());
    for (intptr_t i = 0, n = fields.Length(); i < n; ++i) {
      field ^= fields.At(i);
      name = field.name();
      library.AddObject(field, name);
    }
  }
}

// TODO(alexmarkov): unify with
// TranslationHelper::SetupFieldAccessorFunction.
void BytecodeReaderHelper::SetupFieldAccessorFunction(
    const Class& klass,
    const Function& function,
    const AbstractType& field_type) {
  bool is_setter = function.IsImplicitSetterFunction();
  bool is_method = !function.IsStaticFunction();
  intptr_t parameter_count = (is_method ? 1 : 0) + (is_setter ? 1 : 0);

  const FunctionType& signature = FunctionType::Handle(Z, function.signature());
  signature.SetNumOptionalParameters(0, false);
  signature.set_num_fixed_parameters(parameter_count);
  if (parameter_count > 0) {
    signature.set_parameter_types(
        Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
  }
  NOT_IN_PRECOMPILED(function.CreateNameArray());

  intptr_t pos = 0;
  if (is_method) {
    signature.SetParameterTypeAt(
        pos, AbstractType::Handle(Z, klass.DeclarationType()));
    NOT_IN_PRECOMPILED(function.SetParameterNameAt(pos, Symbols::This()));
    pos++;
  }
  if (is_setter) {
    signature.SetParameterTypeAt(pos, field_type);
    NOT_IN_PRECOMPILED(function.SetParameterNameAt(pos, Symbols::Value()));
    pos++;
  }
}

PatchClassPtr BytecodeReaderHelper::GetPatchClass(const Class& cls,
                                                  const Script& script) {
  if (patch_class_ != nullptr && patch_class_->wrapped_class() == cls.ptr() &&
      patch_class_->script() == script.ptr()) {
    return patch_class_->ptr();
  }
  if (patch_class_ == nullptr) {
    patch_class_ = &PatchClass::Handle(Z);
  }
  *patch_class_ = PatchClass::New(cls, KernelProgramInfo::Handle(Z), script);
  return patch_class_->ptr();
}

InstancePtr BytecodeReaderHelper::Canonicalize(const Instance& instance) {
  if (instance.IsNull()) return instance.ptr();
  return instance.Canonicalize(thread_);
}

void BytecodeReaderHelper::ReadFunctionDeclarations(const Class& cls) {
  // Function flags, must be in sync with FunctionDeclaration constants in
  // pkg/dart2bytecode/lib/declarations.dart.
  const int kIsStaticFlag = 1 << 0;
  const int kIsAbstractFlag = 1 << 1;
  const int kIsGetterFlag = 1 << 2;
  const int kIsSetterFlag = 1 << 3;
  const int kIsConstructorFlag = 1 << 4;
  const int kIsFactoryFlag = 1 << 5;
  const int kIsConstFlag = 1 << 6;
  const int kHasOptionalPositionalParamsFlag = 1 << 7;
  const int kHasOptionalNamedParamsFlag = 1 << 8;
  const int kHasTypeParamsFlag = 1 << 9;
  const int kHasParameterFlagsFlag = 1 << 10;
  const int kIsExtensionMemberFlag = 1 << 11;
  const int kIsReflectableFlag = 1 << 12;
  const int kIsDebuggableFlag = 1 << 13;
  const int kIsAsyncFlag = 1 << 14;
  const int kIsAsyncStarFlag = 1 << 15;
  const int kIsSyncStarFlag = 1 << 16;
  const int kIsNoSuchMethodForwarderFlag = 1 << 17;
  const int kIsExternalFlag = 1 << 18;
  const int kIsNativeFlag = 1 << 19;
  const int kHasSourcePositionsFlag = 1 << 20;
  const int kHasAnnotationsFlag = 1 << 21;
  const int kHasPragmaFlag = 1 << 22;
  const int kHasCustomScriptFlag = 1 << 23;

  const intptr_t num_functions = reader_.ReadListLength();
  ASSERT(function_index_ + num_functions == functions_->Length());

  if (function_index_ + num_functions == 0) {
    return;
  }

  String& name = String::Handle(Z);
  Object& script_class = Object::Handle(Z);
  FunctionType& signature = FunctionType::Handle(Z);
  Function& function = Function::Handle(Z);
  Array& parameter_types = Array::Handle(Z);
  AbstractType& type = AbstractType::Handle(Z);

  name = cls.ScrubbedName();

  for (intptr_t i = 0; i < num_functions; ++i) {
    intptr_t flags = reader_.ReadUInt();

    const bool is_static = (flags & kIsStaticFlag) != 0;
    const bool is_factory = (flags & kIsFactoryFlag) != 0;
    const bool is_native = (flags & kIsNativeFlag) != 0;
    const bool has_pragma = (flags & kHasPragmaFlag) != 0;
    const bool is_extension_member = (flags & kIsExtensionMemberFlag) != 0;

    name ^= ReadObject();

    if ((flags & kHasCustomScriptFlag) != 0) {
      Script& script = Script::CheckedHandle(Z, ReadObject());
      script_class = GetPatchClass(cls, script);
    } else {
      script_class = cls.ptr();
    }

    TokenPosition position = TokenPosition::kNoSource;
    TokenPosition end_position = TokenPosition::kNoSource;
    if ((flags & kHasSourcePositionsFlag) != 0) {
      position = reader_.ReadPosition();
      end_position = reader_.ReadPosition();
    }

    UntaggedFunction::Kind kind = UntaggedFunction::kRegularFunction;
    if ((flags & kIsGetterFlag) != 0) {
      kind = UntaggedFunction::kGetterFunction;
    } else if ((flags & kIsSetterFlag) != 0) {
      kind = UntaggedFunction::kSetterFunction;
    } else if ((flags & (kIsConstructorFlag | kIsFactoryFlag)) != 0) {
      kind = UntaggedFunction::kConstructor;
      name = ConstructorName(cls, name);
    }

    signature = FunctionType::New();
    function = Function::New(
        signature, name, kind, is_static, (flags & kIsConstFlag) != 0,
        (flags & kIsAbstractFlag) != 0, (flags & kIsExternalFlag) != 0,
        is_native, script_class, position);

    // Declare function scope as types (type parameters) in function
    // signature may back-reference to the function being declared.
    // At this moment, owner class is not fully loaded yet and it won't be
    // able to serve function lookup requests.
    FunctionScope function_scope(this, function, name, cls);
    FunctionTypeScope function_type_scope(this, signature);

    function.set_has_pragma(has_pragma);
    NOT_IN_PRECOMPILED(function.set_end_token_pos(end_position));
    function.set_is_synthetic((flags & kIsNoSuchMethodForwarderFlag) != 0);
    function.set_is_reflectable((flags & kIsReflectableFlag) != 0);
    function.set_is_debuggable((flags & kIsDebuggableFlag) != 0);
    function.set_is_extension_member(is_extension_member);

    if ((flags & kIsSyncStarFlag) != 0) {
      function.set_modifier(UntaggedFunction::kSyncGen);
      function.set_is_inlinable(false);
    } else if ((flags & kIsAsyncFlag) != 0) {
      function.set_modifier(UntaggedFunction::kAsync);
      function.set_is_inlinable(false);
    } else if ((flags & kIsAsyncStarFlag) != 0) {
      function.set_modifier(UntaggedFunction::kAsyncGen);
      function.set_is_inlinable(false);
    }

    if ((flags & kHasTypeParamsFlag) != 0) {
      ReadTypeParametersDeclaration(Class::Handle(Z), signature);
    }

    const intptr_t num_implicit_params = (!is_static || is_factory) ? 1 : 0;
    const intptr_t num_params = num_implicit_params + reader_.ReadUInt();
    const bool has_optional_named_params =
        ((flags & kHasOptionalNamedParamsFlag) != 0);

    intptr_t num_required_params = num_params;
    if ((flags & (kHasOptionalPositionalParamsFlag |
                  kHasOptionalNamedParamsFlag)) != 0) {
      num_required_params = num_implicit_params + reader_.ReadUInt();
    }

    signature.set_num_fixed_parameters(num_required_params);
    signature.SetNumOptionalParameters(num_params - num_required_params,
                                       !has_optional_named_params);

    if (num_params > 0) {
      parameter_types = Array::New(num_params, Heap::kOld);
      signature.set_parameter_types(parameter_types);
      signature.CreateNameArrayIncludingFlags(Heap::kOld);
      NOT_IN_PRECOMPILED(function.CreateNameArray());
    }

    intptr_t param_index = 0;
    if (!is_static) {
      type = cls.DeclarationType();
      signature.SetParameterTypeAt(param_index, type);
      NOT_IN_PRECOMPILED(
          function.SetParameterNameAt(param_index, Symbols::This()));
      ++param_index;
    } else if (is_factory) {
      signature.SetParameterTypeAt(param_index, AbstractType::dynamic_type());
      NOT_IN_PRECOMPILED(function.SetParameterNameAt(
          param_index, Symbols::TypeArgumentsParameter()));
      ++param_index;
    }

    for (; param_index < num_params; ++param_index) {
      name ^= ReadObject();
      if (has_optional_named_params && (param_index >= num_required_params)) {
        signature.SetParameterNameAt(param_index, name);
      } else {
        NOT_IN_PRECOMPILED(function.SetParameterNameAt(param_index, name));
      }
      type ^= ReadObject();
      signature.SetParameterTypeAt(param_index, type);
    }

    if ((flags & kHasParameterFlagsFlag) != 0) {
      RELEASE_ASSERT(function.HasOptionalNamedParameters());
      const intptr_t length = reader_.ReadUInt();
      for (intptr_t i = 0; i < length; i++) {
        const intptr_t param_flags = reader_.ReadUInt();
        if ((param_flags & Parameter::kIsRequiredFlag) != 0) {
          signature.SetIsRequiredAt(num_required_params + i);
        }
      }
    }

    type ^= ReadObject();
    signature.set_result_type(type);

    if (is_native) {
      name ^= ReadObject();
      function.set_native_name(name);
    }

    if ((flags & kIsAbstractFlag) == 0) {
      const intptr_t code_offset = reader_.ReadUInt();
      BytecodeLoader* loader = thread_->bytecode_loader();
      ASSERT(loader != nullptr);
      loader->SetOffset(function,
                        code_offset + bytecode_component_->GetCodesOffset());
    }

    if ((flags & kHasAnnotationsFlag) != 0) {
      ReadAnnotations(cls, function, has_pragma);
    }

    functions_->SetAt(function_index_++, function);
  }

  {
    Thread* thread = Thread::Current();
    SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
    cls.SetFunctions(*functions_);
  }

  if (cls.IsTopLevel()) {
    const Library& library = Library::Handle(Z, cls.library());
    for (intptr_t i = 0, n = functions_->Length(); i < n; ++i) {
      function ^= functions_->At(i);
      name = function.name();
      library.AddObject(function, name);
    }
  }

  functions_ = nullptr;
}

void BytecodeReaderHelper::LoadReferencedClass(const Class& cls) {
  ASSERT(!cls.is_declaration_loaded());

  if (!cls.is_declared_in_bytecode()) {
    cls.EnsureDeclarationLoaded();
    return;
  }

  BytecodeLoader* loader = thread_->bytecode_loader();
  ASSERT(loader != nullptr);

  AlternativeReadingScope alt(&reader_, loader->GetOffset(cls));
  ReadClassDeclaration(cls);
}

void BytecodeReaderHelper::ReadClassDeclaration(const Class& cls) {
  // Class flags, must be in sync with ClassDeclaration constants in
  // pkg/dart2bytecode/lib/declarations.dart.
  const int kIsAbstractFlag = 1 << 0;
  const int kIsEnumFlag = 1 << 1;
  const int kHasTypeParamsFlag = 1 << 2;
  const int kHasTypeArgumentsFlag = 1 << 3;
  const int kIsTransformedMixinApplicationFlag = 1 << 4;
  const int kHasSourcePositionsFlag = 1 << 5;
  const int kHasAnnotationsFlag = 1 << 6;
  const int kHasPragmaFlag = 1 << 7;
  const int kHasConstConstructorFlag = 1 << 8;
  const int kIsSealedFlag = 1 << 9;
  const int kIsMixinClassFlag = 1 << 10;
  const int kIsBaseClassFlag = 1 << 11;
  const int kIsInterfaceFlag = 1 << 12;
  const int kIsFinalFlag = 1 << 13;

  // Class is allocated when reading library declaration in
  // BytecodeReaderHelper::ReadLibraryDeclaration.
  // Its cid is set in Class::New / IsolateGroup::RegisterClass /
  // ClassTable::Register, unless it was loaded for expression evaluation.
  ASSERT(cls.is_declared_in_bytecode());
  ASSERT(!cls.is_declaration_loaded());

  const intptr_t flags = reader_.ReadUInt();
  const bool has_pragma = (flags & kHasPragmaFlag) != 0;

  // Set early to enable access to type_parameters().
  // TODO(alexmarkov): revise early stamping of native wrapper classes
  //  as loaded.
  if (!cls.is_declaration_loaded()) {
    cls.set_is_declaration_loaded();
  }

  const auto& script = Script::CheckedHandle(Z, ReadObject());
  cls.set_script(script);

  TokenPosition position = TokenPosition::kNoSource;
  TokenPosition end_position = TokenPosition::kNoSource;
  if ((flags & kHasSourcePositionsFlag) != 0) {
    position = reader_.ReadPosition();
    end_position = reader_.ReadPosition();
    NOT_IN_PRECOMPILED(cls.set_token_pos(position));
    NOT_IN_PRECOMPILED(cls.set_end_token_pos(end_position));
  }

  cls.set_has_pragma(has_pragma);

  if ((flags & kIsAbstractFlag) != 0) {
    cls.set_is_abstract();
  }
  if ((flags & kIsEnumFlag) != 0) {
    cls.set_is_enum_class();
  }
  if ((flags & kIsTransformedMixinApplicationFlag) != 0) {
    cls.set_is_transformed_mixin_application();
  }
  if ((flags & kHasConstConstructorFlag) != 0) {
    cls.set_is_const();
  }
  if ((flags & kIsSealedFlag) != 0) {
    cls.set_is_sealed();
  }
  if ((flags & kIsMixinClassFlag) != 0) {
    cls.set_is_mixin_class();
  }
  if ((flags & kIsBaseClassFlag) != 0) {
    cls.set_is_base_class();
  }
  if ((flags & kIsInterfaceFlag) != 0) {
    cls.set_is_interface_class();
  }
  if ((flags & kIsFinalFlag) != 0) {
    cls.set_is_final();
  }

  intptr_t num_type_arguments = 0;
  if ((flags & kHasTypeArgumentsFlag) != 0) {
    num_type_arguments = reader_.ReadUInt();
  }
  cls.set_num_type_arguments(num_type_arguments);

  if ((flags & kHasTypeParamsFlag) != 0) {
    ReadTypeParametersDeclaration(cls, Object::null_function_type());
  }

  auto& type = AbstractType::CheckedHandle(Z, ReadObject());
  if (!type.IsNull()) {
    cls.set_super_type(Type::Cast(type));
  }

  const intptr_t num_interfaces = reader_.ReadUInt();
  if (num_interfaces > 0) {
    const auto& interfaces =
        Array::Handle(Z, Array::New(num_interfaces, Heap::kOld));
    for (intptr_t i = 0; i < num_interfaces; ++i) {
      type ^= ReadObject();
      interfaces.SetAt(i, type);
    }
    cls.set_interfaces(interfaces);
  }

  if ((flags & kHasAnnotationsFlag) != 0) {
    ReadAnnotations(cls, cls, has_pragma);
  }

  const intptr_t members_offset = reader_.ReadUInt();
  BytecodeLoader* loader = thread_->bytecode_loader();
  ASSERT(loader != nullptr);
  loader->SetOffset(cls,
                    members_offset + bytecode_component_->GetMembersOffset());

  if (!cls.is_type_finalized()) {
    ClassFinalizer::FinalizeTypesInClass(cls);
  }
}

void BytecodeReaderHelper::ReadLibraryDeclaration(
    const Library& library,
    const GrowableObjectArray& pending_classes) {
  // Library flags, must be in sync with LibraryDeclaration constants in
  // pkg/dart2bytecode/lib/declarations.dart.
  // const int kUsesDartMirrorsFlag = 1 << 0;
  // const int kUsesDartFfiFlag = 1 << 1;

  ASSERT(!library.Loaded());
  ASSERT(library.toplevel_class() == Object::null());

  // TODO(alexmarkov): fill in library.used_scripts.

  reader_.ReadUInt();  // Flags.

  auto& name = String::CheckedHandle(Z, ReadObject());
  ASSERT(name.ptr() !=
         Symbols::Symbol(Symbols::kDartNativeWrappersLibNameId).ptr());
  library.SetName(name);

  const auto& script = Script::CheckedHandle(Z, ReadObject());

  library.SetLoadInProgress();

  const intptr_t num_classes = reader_.ReadUInt();
  ASSERT(num_classes > 0);
  auto& cls = Class::Handle(Z);

  for (intptr_t i = 0; i < num_classes; ++i) {
    name ^= ReadObject();
    const intptr_t class_offset =
        bytecode_component_->GetClassesOffset() + reader_.ReadUInt();

    if (i == 0) {
      ASSERT(name.ptr() == Symbols::Empty().ptr());
      cls = Class::New(library, Symbols::TopLevel(), script,
                       TokenPosition::kNoSource, /*register_class=*/true);
      cls.set_is_declared_in_bytecode(true);
      library.set_toplevel_class(cls);
    } else {
      cls = Class::New(library, name, script, TokenPosition::kNoSource,
                       /*register_class=*/true);
      cls.set_is_declared_in_bytecode(true);
      library.AddClass(cls);
    }

    BytecodeLoader* loader = thread_->bytecode_loader();
    ASSERT(loader != nullptr);
    loader->SetOffset(cls, class_offset);
    pending_classes.Add(cls);
  }

  ASSERT(!library.Loaded());
  library.SetLoaded();
}

void BytecodeReaderHelper::ReadLibraryDeclarations(
    intptr_t num_libraries,
    const GrowableObjectArray& pending_classes,
    bool load_code) {
  auto& library = Library::Handle(Z);
  auto& uri = String::Handle(Z);

  // Verify that libraries in the dynamic module are not loaded yet.
  {
    AlternativeReadingScope alt(&reader_, reader_.offset());
    for (intptr_t i = 0; i < num_libraries; ++i) {
      uri ^= ReadObject();
      reader_.ReadUInt();  // Skip library offset.

      library = Library::LookupLibrary(thread_, uri);
      if (!library.IsNull()) {
        const String& msg = String::Handle(String::NewFormatted(
            "Unable to load dynamic module: library \'%s\' is already loaded",
            uri.ToCString()));
        Exceptions::ThrowStateError(msg);
      }
    }
  }

  for (intptr_t i = 0; i < num_libraries; ++i) {
    uri ^= ReadObject();
    const intptr_t library_offset =
        bytecode_component_->GetLibrariesOffset() + reader_.ReadUInt();

    library = Library::New(uri);
    library.Register(thread_);
    ASSERT(!library.Loaded());

    AlternativeReadingScope alt(&reader_, library_offset);
    ReadLibraryDeclaration(library, pending_classes);
  }

  if (load_code) {
    ReadPendingCode(pending_classes);
  }
}

void BytecodeReaderHelper::ReadPendingCode(
    const GrowableObjectArray& pending_classes) {
  auto& cls = Class::Handle(Z);
  auto& error = Error::Handle(Z);
  auto& members = Array::Handle(Z);
  auto& function = Function::Handle(Z);
  auto& field = Field::Handle(Z);
  for (intptr_t i = 0, n = pending_classes.Length(); i < n; ++i) {
    cls ^= pending_classes.At(i);
    error = cls.EnsureIsFinalized(thread_);
    if (!error.IsNull()) {
      Exceptions::PropagateError(error);
      UNREACHABLE();
    }
    members = cls.functions();
    for (intptr_t j = 0, m = members.Length(); j < m; ++j) {
      function ^= members.At(j);
      if (!function.is_abstract() && !function.HasBytecode()) {
        ReadCode(function, thread_->bytecode_loader()->GetOffset(function));
      }
    }
    members = cls.fields();
    for (intptr_t j = 0, m = members.Length(); j < m; ++j) {
      field ^= members.At(j);
      if (field.has_nontrivial_initializer()) {
        if (field.is_static() || field.is_late() ||
            thread_->bytecode_loader()->HasOffset(field)) {
          function = field.EnsureInitializerFunction();
          if (!function.HasBytecode()) {
            ReadCode(function, thread_->bytecode_loader()->GetOffset(field));
          }
        }
      }
    }
  }
}

void BytecodeReaderHelper::FindModifiedLibraries(BitVector* modified_libs,
                                                 intptr_t num_libraries) {
  auto& uri = String::Handle(Z);
  auto& lib = Library::Handle(Z);
  for (intptr_t i = 0; i < num_libraries; ++i) {
    uri ^= ReadObject();
    reader_.ReadUInt();  // Skip offset.

    lib = Library::LookupLibrary(thread_, uri);
    if (!lib.IsNull() && !lib.is_dart_scheme()) {
      // This is a library that already exists so mark it as being modified.
      modified_libs->Add(lib.index());
    }
  }
}

void BytecodeReaderHelper::ReadParameterCovariance(
    const Function& function,
    intptr_t code_offset,
    BitVector* is_covariant,
    BitVector* is_generic_covariant_impl) {
  ASSERT(function.is_declared_in_bytecode());

  const intptr_t num_params = function.NumParameters();
  ASSERT(is_covariant->length() == num_params);
  ASSERT(is_generic_covariant_impl->length() == num_params);

  AlternativeReadingScope alt(&reader_, code_offset);

  const intptr_t code_flags = reader_.ReadUInt();
  if ((code_flags & Code::kHasParameterFlagsFlag) != 0) {
    const intptr_t num_explicit_params = reader_.ReadUInt();
    ASSERT(num_params ==
           function.NumImplicitParameters() + num_explicit_params);

    for (intptr_t i = function.NumImplicitParameters(); i < num_params; ++i) {
      const intptr_t flags = reader_.ReadUInt();

      if ((flags & Parameter::kIsCovariantFlag) != 0) {
        is_covariant->Add(i);
      }
      if ((flags & Parameter::kIsCovariantByClassFlag) != 0) {
        is_generic_covariant_impl->Add(i);
      }
    }
  }
}

LibraryPtr BytecodeReaderHelper::ReadMain() {
  return Library::RawCast(ReadObject());
}

TypedDataBasePtr BytecodeComponentData::GetTypedData() const {
  return TypedDataBase::RawCast(data_.At(kTypedData));
}

intptr_t BytecodeComponentData::GetVersion() const {
  return Smi::Value(Smi::RawCast(data_.At(kVersion)));
}

intptr_t BytecodeComponentData::GetStringsHeaderOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kStringsHeaderOffset)));
}

intptr_t BytecodeComponentData::GetStringsContentsOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kStringsContentsOffset)));
}

intptr_t BytecodeComponentData::GetObjectOffsetsOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kObjectOffsetsOffset)));
}

intptr_t BytecodeComponentData::GetNumObjects() const {
  return Smi::Value(Smi::RawCast(data_.At(kNumObjects)));
}

intptr_t BytecodeComponentData::GetObjectsContentsOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kObjectsContentsOffset)));
}

intptr_t BytecodeComponentData::GetMainOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kMainOffset)));
}

intptr_t BytecodeComponentData::GetNumLibraries() const {
  return Smi::Value(Smi::RawCast(data_.At(kNumLibraries)));
}

intptr_t BytecodeComponentData::GetLibraryIndexOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kLibraryIndexOffset)));
}

intptr_t BytecodeComponentData::GetLibrariesOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kLibrariesOffset)));
}

intptr_t BytecodeComponentData::GetNumClasses() const {
  return Smi::Value(Smi::RawCast(data_.At(kNumClasses)));
}

intptr_t BytecodeComponentData::GetClassesOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kClassesOffset)));
}

intptr_t BytecodeComponentData::GetMembersOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kMembersOffset)));
}

intptr_t BytecodeComponentData::GetNumCodes() const {
  return Smi::Value(Smi::RawCast(data_.At(kNumCodes)));
}

intptr_t BytecodeComponentData::GetCodesOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kCodesOffset)));
}

intptr_t BytecodeComponentData::GetSourcePositionsOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kSourcePositionsOffset)));
}

intptr_t BytecodeComponentData::GetSourceFilesOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kSourceFilesOffset)));
}

intptr_t BytecodeComponentData::GetLineStartsOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kLineStartsOffset)));
}

intptr_t BytecodeComponentData::GetLocalVariablesOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kLocalVariablesOffset)));
}

intptr_t BytecodeComponentData::GetAnnotationsOffset() const {
  return Smi::Value(Smi::RawCast(data_.At(kAnnotationsOffset)));
}

void BytecodeComponentData::SetObject(intptr_t index, const Object& obj) const {
  data_.SetAt(kNumFields + index, obj);
}

ObjectPtr BytecodeComponentData::GetObject(intptr_t index) const {
  return data_.At(kNumFields + index);
}

ArrayPtr BytecodeComponentData::New(Zone* zone,
                                    const TypedDataBase& typed_data,
                                    intptr_t version,
                                    intptr_t num_objects,
                                    intptr_t strings_header_offset,
                                    intptr_t strings_contents_offset,
                                    intptr_t object_offsets_offset,
                                    intptr_t objects_contents_offset,
                                    intptr_t main_offset,
                                    intptr_t num_libraries,
                                    intptr_t library_index_offset,
                                    intptr_t libraries_offset,
                                    intptr_t num_classes,
                                    intptr_t classes_offset,
                                    intptr_t members_offset,
                                    intptr_t num_codes,
                                    intptr_t codes_offset,
                                    intptr_t source_positions_offset,
                                    intptr_t source_files_offset,
                                    intptr_t line_starts_offset,
                                    intptr_t local_variables_offset,
                                    intptr_t annotations_offset,
                                    Heap::Space space) {
  const Array& data =
      Array::Handle(zone, Array::New(kNumFields + num_objects, space));
  Smi& smi_handle = Smi::Handle(zone);

  data.SetAt(kTypedData, typed_data);

  smi_handle = Smi::New(version);
  data.SetAt(kVersion, smi_handle);

  smi_handle = Smi::New(strings_header_offset);
  data.SetAt(kStringsHeaderOffset, smi_handle);

  smi_handle = Smi::New(strings_contents_offset);
  data.SetAt(kStringsContentsOffset, smi_handle);

  smi_handle = Smi::New(object_offsets_offset);
  data.SetAt(kObjectOffsetsOffset, smi_handle);

  smi_handle = Smi::New(num_objects);
  data.SetAt(kNumObjects, smi_handle);

  smi_handle = Smi::New(objects_contents_offset);
  data.SetAt(kObjectsContentsOffset, smi_handle);

  smi_handle = Smi::New(main_offset);
  data.SetAt(kMainOffset, smi_handle);

  smi_handle = Smi::New(num_libraries);
  data.SetAt(kNumLibraries, smi_handle);

  smi_handle = Smi::New(library_index_offset);
  data.SetAt(kLibraryIndexOffset, smi_handle);

  smi_handle = Smi::New(libraries_offset);
  data.SetAt(kLibrariesOffset, smi_handle);

  smi_handle = Smi::New(num_classes);
  data.SetAt(kNumClasses, smi_handle);

  smi_handle = Smi::New(classes_offset);
  data.SetAt(kClassesOffset, smi_handle);

  smi_handle = Smi::New(members_offset);
  data.SetAt(kMembersOffset, smi_handle);

  smi_handle = Smi::New(num_codes);
  data.SetAt(kNumCodes, smi_handle);

  smi_handle = Smi::New(codes_offset);
  data.SetAt(kCodesOffset, smi_handle);

  smi_handle = Smi::New(source_positions_offset);
  data.SetAt(kSourcePositionsOffset, smi_handle);

  smi_handle = Smi::New(source_files_offset);
  data.SetAt(kSourceFilesOffset, smi_handle);

  smi_handle = Smi::New(line_starts_offset);
  data.SetAt(kLineStartsOffset, smi_handle);

  smi_handle = Smi::New(local_variables_offset);
  data.SetAt(kLocalVariablesOffset, smi_handle);

  smi_handle = Smi::New(annotations_offset);
  data.SetAt(kAnnotationsOffset, smi_handle);

  return data.ptr();
}

void BytecodeReader::LoadClassDeclaration(const Class& cls) {
  ASSERT(cls.is_declared_in_bytecode());
  ASSERT(!cls.is_declaration_loaded());

  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());

  BytecodeLoader* loader = thread->bytecode_loader();
  ASSERT(loader != nullptr);

  BytecodeComponentData bytecode_component(
      Array::Handle(zone, loader->bytecode_component_array()));
  ASSERT(!bytecode_component.IsNull());
  BytecodeReaderHelper bytecode_reader(thread, &bytecode_component);

  AlternativeReadingScope alt(&bytecode_reader.reader(),
                              loader->GetOffset(cls));
  bytecode_reader.ReadClassDeclaration(cls);
}

void BytecodeReader::FinishClassLoading(const Class& cls) {
  ASSERT(cls.is_declared_in_bytecode());

  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());

  BytecodeLoader* loader = thread->bytecode_loader();
  ASSERT(loader != nullptr);

  BytecodeComponentData bytecode_component(
      Array::Handle(zone, loader->bytecode_component_array()));
  ASSERT(!bytecode_component.IsNull());
  BytecodeReaderHelper bytecode_reader(thread, &bytecode_component);

  AlternativeReadingScope alt(&bytecode_reader.reader(),
                              loader->GetOffset(cls));

  // If this is a dart:internal.ClassID class ignore field declarations
  // contained in the Kernel file and instead inject our own const
  // fields.
  const bool discard_fields = cls.InjectCIDFields();

  bytecode_reader.ReadMembers(cls, discard_fields);
}

void BytecodeReader::ReadParameterCovariance(
    const Function& function,
    BitVector* is_covariant,
    BitVector* is_generic_covariant_impl) {
  ASSERT(function.is_declared_in_bytecode());
  ASSERT(!function.IsClosureFunction());

  // Method extractors of abstract methods are only used as
  // targets of interface calls, so covariance of parameters is irrelevant.
  if (function.is_abstract()) {
    return;
  }

  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  auto& binary = TypedDataBase::Handle(zone);
  intptr_t offset = 0;

  const auto& bytecode = Bytecode::Handle(zone, function.GetBytecode());
  if (bytecode.IsNull()) {
    BytecodeLoader* loader = thread->bytecode_loader();
    ASSERT(loader != nullptr);
    binary = loader->binary();
    offset = loader->GetOffset(function);
  } else {
    binary = bytecode.binary();
    ASSERT(!binary.IsNull());
    offset = bytecode.code_offset();
    ASSERT(offset > 0);
  }
  BytecodeReaderHelper bytecode_reader(thread, binary);
  bytecode_reader.ReadParameterCovariance(function, offset, is_covariant,
                                          is_generic_covariant_impl);
}

static void CollectTokenPosition(TokenPosition token_pos,
                                 GrowableArray<intptr_t>* token_positions) {
  if (!token_pos.IsReal()) {
    return;
  }
  const intptr_t token_pos_value = token_pos.Serialize();
  if (!token_positions->is_empty() &&
      token_positions->Last() == token_pos_value) {
    return;
  }
  token_positions->Add(token_pos_value);
}

static void CollectBytecodeFunctionTokenPositions(
    Zone* zone,
    const Function& function,
    GrowableArray<intptr_t>* token_positions) {
  ASSERT(function.is_declared_in_bytecode());
  CollectTokenPosition(function.token_pos(), token_positions);
  CollectTokenPosition(function.end_token_pos(), token_positions);
  if (!function.HasBytecode()) {
    return;
  }
  Bytecode& bytecode = Bytecode::Handle(zone, function.GetBytecode());
  ASSERT(!bytecode.IsNull());
  if (bytecode.HasSourcePositions()) {
    BytecodeSourcePositionsIterator iter(zone, bytecode);
    while (iter.MoveNext()) {
      CollectTokenPosition(iter.TokenPos(), token_positions);
    }
    if (!function.IsNonImplicitClosureFunction()) {
      // Find closure functions in the object pool.
      const ObjectPool& pool = ObjectPool::Handle(zone, bytecode.object_pool());
      Object& object = Object::Handle(zone);
      for (intptr_t i = 0; i < pool.Length(); i++) {
        ObjectPool::EntryType entry_type = pool.TypeAt(i);
        if (entry_type != ObjectPool::EntryType::kTaggedObject) {
          continue;
        }
        object = pool.ObjectAt(i);
        if (object.IsFunction()) {
          const auto& closure = Function::Cast(object);
          if (closure.IsNonImplicitClosureFunction()) {
            CollectBytecodeFunctionTokenPositions(zone, closure,
                                                  token_positions);
          }
        }
      }
    }
  }
}

void BytecodeReader::CollectScriptTokenPositionsFromBytecode(
    const Script& interesting_script,
    GrowableArray<intptr_t>* token_positions) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
      zone, thread->isolate_group()->object_store()->libraries());
  auto& lib = Library::Handle(zone);
  auto& cls = Class::Handle(zone);
  auto& array = Array::Handle(zone);
  auto& function = Function::Handle(zone);
  auto& field = Field::Handle(zone);

  for (intptr_t i = 0, n = libs.Length(); i < n; ++i) {
    lib ^= libs.At(i);
    cls = lib.toplevel_class();
    if (!cls.is_declared_in_bytecode()) {
      continue;
    }
    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
    while (it.HasNext()) {
      cls = it.GetNextClass();
      ASSERT(cls.is_declared_in_bytecode());
      if (cls.script() == interesting_script.ptr()) {
        CollectTokenPosition(cls.token_pos(), token_positions);
        CollectTokenPosition(cls.end_token_pos(), token_positions);
      }
      array = cls.fields();
      for (intptr_t i = 0, n = array.Length(); i < n; ++i) {
        field ^= array.At(i);
        if (field.Script() != interesting_script.ptr()) {
          continue;
        }
        CollectTokenPosition(field.token_pos(), token_positions);
        CollectTokenPosition(field.end_token_pos(), token_positions);
        if ((field.is_static() || field.is_late()) &&
            field.has_nontrivial_initializer()) {
          function = field.EnsureInitializerFunction();
          CollectBytecodeFunctionTokenPositions(zone, function,
                                                token_positions);
        }
      }
      array = cls.current_functions();
      for (intptr_t i = 0, n = array.Length(); i < n; ++i) {
        function ^= array.At(i);
        if (function.script() != interesting_script.ptr()) {
          continue;
        }
        CollectBytecodeFunctionTokenPositions(zone, function, token_positions);
      }
    }
  }
}

#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

LocalVarDescriptorsPtr BytecodeReader::ComputeLocalVarDescriptors(
    Zone* zone,
    const Function& function,
    const Bytecode& bytecode) {
  ASSERT(function.is_declared_in_bytecode());
  ASSERT(function.HasBytecode());
  ASSERT(!bytecode.IsNull());
  ASSERT(function.GetBytecode() == bytecode.ptr());

  LocalVarDescriptorsBuilder vars;

  if (function.IsLocalFunction()) {
    const auto& parent = Function::Handle(zone, function.parent_function());
    ASSERT(parent.is_declared_in_bytecode() && parent.HasBytecode());
    const auto& parent_bytecode = Bytecode::Handle(zone, parent.GetBytecode());
    const auto& parent_vars = LocalVarDescriptors::Handle(
        zone, parent_bytecode.GetLocalVarDescriptors());
    for (intptr_t i = 0; i < parent_vars.Length(); ++i) {
      UntaggedLocalVarDescriptors::VarInfo var_info;
      parent_vars.GetInfo(i, &var_info);
      // Include parent's context variable if variable's scope
      // intersects with the local function range.
      // It is not enough to check if local function is declared within the
      // scope of variable, because in case of async functions closure has
      // the same range as original function.
      if (var_info.kind() == UntaggedLocalVarDescriptors::kContextVar &&
          ((var_info.begin_pos <= function.token_pos() &&
            function.token_pos() <= var_info.end_pos) ||
           (function.token_pos() <= var_info.begin_pos &&
            var_info.begin_pos <= function.end_token_pos()))) {
        vars.Add(LocalVarDescriptorsBuilder::VarDesc{
            &String::Handle(zone, parent_vars.GetName(i)), var_info});
      }
    }
  }

  if (bytecode.HasLocalVariablesInfo()) {
    intptr_t scope_id = 0;
    intptr_t context_level = -1;
    BytecodeLocalVariablesIterator local_vars(zone, bytecode);
    while (local_vars.MoveNext()) {
      switch (local_vars.Kind()) {
        case BytecodeLocalVariablesIterator::kScope: {
          ++scope_id;
          context_level = local_vars.ContextLevel();
        } break;
        case BytecodeLocalVariablesIterator::kVariableDeclaration: {
          LocalVarDescriptorsBuilder::VarDesc desc;
          desc.name = &String::Handle(zone, local_vars.Name());
          if (local_vars.IsCaptured()) {
            desc.info.set_kind(UntaggedLocalVarDescriptors::kContextVar);
            desc.info.scope_id = context_level;
            desc.info.set_index(local_vars.Index());
          } else {
            desc.info.set_kind(UntaggedLocalVarDescriptors::kStackVar);
            desc.info.scope_id = scope_id;
            if (local_vars.Index() < 0) {
              // Parameter
              ASSERT(local_vars.Index() < -kKBCParamEndSlotFromFp);
              desc.info.set_index(-local_vars.Index() - kKBCParamEndSlotFromFp);
            } else {
              desc.info.set_index(-local_vars.Index());
            }
          }
          desc.info.declaration_pos = local_vars.DeclarationTokenPos();
          desc.info.begin_pos = local_vars.StartTokenPos();
          desc.info.end_pos = local_vars.EndTokenPos();
          vars.Add(desc);
        } break;
        case BytecodeLocalVariablesIterator::kContextVariable: {
          ASSERT(local_vars.Index() >= 0);
          const intptr_t context_variable_index = -local_vars.Index();
          LocalVarDescriptorsBuilder::VarDesc desc;
          desc.name = &Symbols::CurrentContextVar();
          desc.info.set_kind(UntaggedLocalVarDescriptors::kSavedCurrentContext);
          desc.info.scope_id = 0;
          desc.info.declaration_pos = TokenPosition::kMinSource;
          desc.info.begin_pos = TokenPosition::kMinSource;
          desc.info.end_pos = TokenPosition::kMinSource;
          desc.info.set_index(context_variable_index);
          vars.Add(desc);
        } break;
      }
    }
  }

  return vars.Done();
}

#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

}  // namespace bytecode
}  // namespace dart

#endif  // defined(DART_DYNAMIC_MODULES)
