// 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.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");
DEFINE_FLAG(charp,
            dump_kernel_bytecode_filter,
            nullptr,
            "Dump only kernel bytecode of functions with matching names");

namespace bytecode {

static bool ShouldPrint(const Function& function) {
  return function.NamePassesFilter(FLAG_dump_kernel_bytecode_filter);
}

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 if (key.IsScript()) {
      return String::Hash(Script::Cast(key).url());
    } 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_objects_(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_objects_, 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_objects_);
}

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) {
    if (ShouldPrint(function)) {
      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;
      const bool captures_only_final_not_late_vars =
          (flags & ClosureCode::kCapturesOnlyFinalNotLateVarsFlag) != 0;

      intptr_t local_function_id = -1;
      if ((flags & ClosureCode::kHasLocalFunctionIdFlag) != 0) {
        local_function_id = reader_.ReadUInt();
        ASSERT(local_function_id > 0);
      }

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

      closure.set_captures_only_final_not_late_vars(
          captures_only_final_not_late_vars);
      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) {
        if (ShouldPrint(closure)) {
          KernelBytecodeDisassembler::Disassemble(closure);
        }
      }

      ClosureFunctionsCache::AddClosureFunctionLocked(closure,
                                                      local_function_id);
    }
  }
}

void BytecodeReaderHelper::ReadCoveredConstConstructors(const Script& script,
                                                        intptr_t offset) {
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
  AlternativeReadingScope alt(&reader_, offset);
  const intptr_t len = reader_.ReadListLength();
  const auto& constant_coverage = Array::Handle(Z, Array::New(len, Heap::kOld));
  auto& function = Function::Handle(Z);
  for (intptr_t i = 0; i < len; i++) {
    function ^= ReadObject();
    // Const constructors from extension types can be desugared into procedures.
    ASSERT(function.IsFunction() && function.is_const());
    constant_coverage.SetAt(i, function);
  }
  script.set_collected_constant_coverage(constant_coverage);
#else
  UNREACHABLE();
#endif
}

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 int kHasAnnotationsFlag = 1 << 9;
  const int kHasPragmaFlag = 1 << 10;
  const int kIsInvisibleFlag = 1 << 11;

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

  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);
  closure.set_is_visible((flags & kIsInvisibleFlag) == 0);
  closure.set_has_pragma(has_pragma);

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

  if ((flags & kHasAnnotationsFlag) != 0) {
    ReadAnnotations(Class::Handle(Z, Function::Cast(parent).Owner()), closure,
                    has_pragma);
  }
}

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,
    kFfiCall,
    kDeferredLibraryPrefix,
    kAllocateClosure,
  };

  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;
      }
      case ConstantPoolTag::kFfiCall: {
        // FfiCall constant has 1 raw value entry.
        pool.SetTypeAt(i, ObjectPool::EntryType::kNativeFunction,
                       ObjectPool::Patchability::kNotPatchable,
                       ObjectPool::SnapshotBehavior::kNotSnapshotable);
        pool.SetRawValueAt(i, 0);
        continue;
      }
      case ConstantPoolTag::kDeferredLibraryPrefix: {
        name ^= ReadObject();
        ASSERT(name.IsSymbol());
        const auto& enclosing_library = Library::CheckedHandle(Z, ReadObject());
        const auto& target_library = Library::CheckedHandle(Z, ReadObject());
        obj = enclosing_library.LookupLocalLibraryPrefix(name);
        if (obj.IsNull()) {
          obj = Namespace::New(target_library, Object::null_array(),
                               Object::null_array(), enclosing_library);
          obj = LibraryPrefix::New(name, Namespace::Cast(obj),
                                   /*deferred_load=*/true, enclosing_library);
          enclosing_library.AddObject(LibraryPrefix::Cast(obj), name);
        }
        ASSERT(LibraryPrefix::Cast(obj).GetLibrary(0) == target_library.ptr());
      } break;
      case ConstantPoolTag::kAllocateClosure: {
        const intptr_t closure_index = reader_.ReadUInt();
        const intptr_t num_elements = reader_.ReadUInt();
        const intptr_t flags = reader_.ReadUInt();
        // AllocateClosure flags, must be in sync with ConstantAllocateClosure
        // constants in pkg/dart2bytecode/lib/constant_pool.dart.
        const intptr_t kHasDelayedTypeArguments = 1 << 0;
        const intptr_t kHasInstantiatorTypeArguments = 1 << 1;
        const intptr_t kHasFunctionTypeArguments = 1 << 2;
        // AllocateClosure constant occupies 2 entries:
        // function and length_and_flags.
        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);
        ++i;
        ASSERT(i < obj_count);
        // The second entry is used for encoded length and flags.
        obj = Smi::New(UntaggedClosure::EncodeLengthAndFlags(
            (flags & kHasDelayedTypeArguments) != 0,
            (flags & kHasInstantiatorTypeArguments) != 0,
            (flags & kHasFunctionTypeArguments) != 0, num_elements));
      } break;
      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()) {
        // Expression evaluation libraries are not registered with the VM:
        // The expression evaluation functions should be GC-able as soon as
        // they are not reachable anymore and we never look them up by name.
        if (uri.ptr() == Symbols::EvalSourceUri().ptr()) {
          return thread_->bytecode_loader()->GetExpressionEvaluationLibrary();
        }
        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.LookupClass(class_name);
      if (cls == Class::null()) {
        // Expression evaluation class is not added to its library.
        // Any reference to the expression evaluation class should be replaced
        // with a real class.
        if (library.url() == Symbols::EvalSourceUri().ptr()) {
          ASSERT(thread_->bytecode_loader()->GetExpressionEvaluationLibrary() ==
                 library.ptr());
          return thread_->bytecode_loader()->GetExpressionEvaluationRealClass();
        }
        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 {
        const bool is_constructor = (flags & kFlagIsConstructor) != 0;
        if (is_constructor) {
          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();
        }
        // If this is a reference to the expression evaluation function, then
        // reading the class has substituted in the real class.
        if (name.ptr() == Symbols::DebugProcedureName().ptr() &&
            cls.ptr() == thread_->bytecode_loader()
                             ->GetExpressionEvaluationRealClass()) {
          return thread_->bytecode_loader()->GetExpressionEvaluationFunction();
        }
        FunctionPtr function = Function::null();
        ErrorPtr finalize_err = is_constructor
                                    ? cls.EnsureIsAllocateFinalized(thread_)
                                    : cls.EnsureIsFinalized(thread_);
        if (finalize_err != Error::null()) {
          FATAL("Unable to finalize class %s%s: %s", cls.ToCString(),
                is_constructor ? "" : " for allocation",
                Error::Handle(Z, finalize_err).ToErrorCString());
        }
        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: {
      auto& script = Script::Handle(Z);
      const String& uri = String::CheckedHandle(Z, ReadObject());
      if ((flags & kFlagHasSourceFile) != 0) {
        script =
            ReadSourceFile(uri, bytecode_component_->GetSourceFilesOffset() +
                                    reader_.ReadUInt());
      } else {
        script = Script::New(uri, Object::null_string());
      }
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
      // Covered const constructor information for scripts is loaded
      // during ReadPendingCode. For any script that is not pending,
      // set the collected constant coverage to the empty array.
      BytecodeLoader* const loader = thread_->bytecode_loader();
      ASSERT(loader != nullptr);
      if (!loader->HasOffset(script)) {
        script.set_collected_constant_coverage(Object::empty_array());
      }
#endif
      return script.ptr();
    }
    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()) {
        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());
      AbstractType& type =
          AbstractType::Handle(Z, Type::New(cls, type_arguments, nullability));
      type.SetIsFinalized();
      type = type.NormalizeFutureOrType(Heap::kOld);
      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;
  const int kHasCoveredConstConstructorsFlag = 1 << 2;

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

  if ((flags & kHasCoveredConstConstructorsFlag) != 0) {
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
    // Any covered const constructors are read later during
    // ReadPendingCode, which then sets the collected constant
    // coverage for these scripts.
    BytecodeLoader* const loader = thread_->bytecode_loader();
    ASSERT(loader != nullptr);
    loader->AddPendingObject(script, reader_.offset());
#endif
  }

  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 kIsExtensionTypeMemberFlag = 1 << 17;
  const int kIsSharedFlag = 1 << 18;

  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 is_extension_type_member =
        (flags & kIsExtensionTypeMemberFlag) != 0;
    const bool has_initializer = (flags & kHasInitializerFlag) != 0;
    const bool is_shared = (flags & kIsSharedFlag) != 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_is_extension_type_member(is_extension_type_member);
    field.set_has_initializer(has_initializer);
    field.set_is_shared(is_shared);

    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);
      function.set_is_extension_type_member(is_extension_type_member);
      SetupFieldAccessorFunction(cls, function, type);
      if (is_static) {
        if (is_shared) {
          function.AttachBytecode(
              Object::implicit_shared_static_getter_bytecode());
        } else {
          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)) || is_shared);
      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);
      function.set_is_extension_type_member(is_extension_type_member);
      SetupFieldAccessorFunction(cls, function, type);
      if (is_static) {
        if (is_shared) {
          function.AttachBytecode(
              Object::implicit_shared_static_setter_bytecode());
        } else {
          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 int kIsExtensionTypeMemberFlag = 1 << 24;
  const int kIsInvisibleFlag = 1 << 25;

  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_native = (flags & kIsNativeFlag) != 0;
    const bool has_pragma = (flags & kHasPragmaFlag) != 0;
    const bool is_extension_member = (flags & kIsExtensionMemberFlag) != 0;
    const bool is_extension_type_member =
        (flags & kIsExtensionTypeMemberFlag) != 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);

    const bool is_expression_evaluation =
        (name.ptr() == Symbols::DebugProcedureName().ptr());

    // 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);

    // Set the expression evaluation function now so that references to it
    // can be appropriately substituted as needed when reading objects below.
    if (is_expression_evaluation) {
      ASSERT(!function.is_abstract());
      thread_->bytecode_loader()->SetExpressionEvaluationFunction(function);
    }

    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_visible((flags & kIsInvisibleFlag) == 0);
    function.set_is_extension_member(is_extension_member);
    function.set_is_extension_type_member(is_extension_type_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) ? 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) {
      if (is_expression_evaluation) {
        // Do not reference enclosing class as expression evaluation
        // method logically belongs to another (real) class.
        // Enclosing class is not registered and doesn't have
        // a valid cid, so it can't be used in a type.
        type = AbstractType::dynamic_type().ptr();
      } else {
        type = cls.DeclarationType();
      }
      signature.SetParameterTypeAt(param_index, type);
      NOT_IN_PRECOMPILED(
          function.SetParameterNameAt(param_index, Symbols::This()));
      ++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();
      if (!name.IsNull()) {
        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) {
      ASSERT(!is_expression_evaluation);
      ReadAnnotations(cls, function, has_pragma);
    }

    if (is_expression_evaluation) {
      ReadCode(function, thread_->bytecode_loader()->GetOffset(function));
    }

    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;
  const int kIsDeeplyImmutableFlag = 1 << 14;

  // 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();
  }
  if ((flags & kIsDeeplyImmutableFlag) != 0) {
    cls.set_is_deeply_immutable(true);
  }

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

#if !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
  cls.SetUserVisibleNameInClassTable();
#endif
}

void BytecodeReaderHelper::ReadLibraryDeclaration(const Library& library,
                                                  bool register_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_classes);
      cls.set_is_declared_in_bytecode(true);
      library.set_toplevel_class(cls);
    } else {
      cls = Class::New(library, name, script, TokenPosition::kNoSource,
                       register_classes);
      cls.set_is_declared_in_bytecode(true);
      if (register_classes) {
        library.AddClass(cls);
      }
    }

    BytecodeLoader* loader = thread_->bytecode_loader();
    ASSERT(loader != nullptr);
    loader->AddPendingObject(cls, class_offset);
  }

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

void BytecodeReaderHelper::ReadLibraryDeclarations(
    intptr_t num_libraries,
    const GrowableObjectArray& pending_objects,
    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();

    bool register_classes = true;
    library = Library::New(uri);
    if (uri.ptr() == Symbols::EvalSourceUri().ptr()) {
      thread_->bytecode_loader()->SetExpressionEvaluationLibrary(library);
      register_classes = false;
    } else {
      library.Register(thread_);
    }
    ASSERT(!library.Loaded());

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

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

void BytecodeReaderHelper::ReadPendingCode(
    const GrowableObjectArray& pending_objects) {
  auto& obj = Object::Handle(Z);
  auto& error = Error::Handle(Z);
  auto& members = Array::Handle(Z);
  auto& function = Function::Handle(Z);
  auto& field = Field::Handle(Z);
  // Handling pending objects can end up adding new pending objects
  // to the array, so re-retrieve the length for each iteration.
  for (intptr_t i = 0; i < pending_objects.Length(); ++i) {
    obj = pending_objects.At(i);
    ASSERT(!obj.IsNull());
    if (obj.IsClass()) {
      const auto& cls = Class::Cast(obj);
      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));
            }
          }
        }
      }
    } else if (obj.IsScript()) {
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
      const auto& script = Script::Cast(obj);
      ReadCoveredConstConstructors(
          script, thread_->bytecode_loader()->GetOffset(script));
#else
      UNREACHABLE();
#endif
    } else {
      FATAL("Unexpected object %s in pending objects list", obj.ToCString());
    }
  }
}

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)

const char* BytecodeLocalVariablesIterator::kKindNames[] = {
    "Invalid",
    "Scope",
    "VariableDeclaration",
    "ContextVariable",
};

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)
