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

#include "vm/bytecode_reader.h"

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

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

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

namespace dart {

DEFINE_FLAG(bool, dump_kernel_bytecode, false, "Dump kernel bytecode");
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;

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

      ReadExceptionsTable(closure, closure_bytecode, has_exceptions_table);

      ReadSourcePositions(closure_bytecode, has_source_positions);

      ReadLocalVariables(closure_bytecode, has_local_variables);

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

      ClosureFunctionsCache::AddClosureFunctionLocked(closure);
    }
  }
}

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();
    ASSERT(function.IsConstructor() && 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 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_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,
  };

  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;
      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 {
        if ((flags & kFlagIsConstructor) != 0) {
          name = ConstructorName(cls, name);
        }
        ASSERT(!name.IsNull() && name.IsSymbol());
        if (name.ptr() == scoped_function_name_.ptr() &&
            cls.ptr() == scoped_function_class_.ptr()) {
          return scoped_function_.ptr();
        }
        FunctionPtr function = Function::null();
        if ((flags & kFlagIsConstructor) != 0) {
          if (cls.EnsureIsAllocateFinalized(thread_) == Error::null()) {
            function = Resolver::ResolveFunction(Z, cls, name);
          }
        } else {
          if (cls.EnsureIsFinalized(thread_) == Error::null()) {
            function = Resolver::ResolveFunction(Z, cls, name);
          }
        }
        if (function == Function::null()) {
          // When requesting a getter, also return method extractors.
          if (Field::IsGetterName(name)) {
            String& method_name =
                String::Handle(Z, Field::NameFromGetter(name));
            function = Resolver::ResolveFunction(Z, cls, method_name);
            if (function != Function::null()) {
              function = Function::Handle(Z, function).GetMethodExtractor(name);
              if (function != Function::null()) {
                return function;
              }
            }
          }
          FATAL("Unable to find function %s in %s", name.ToCString(),
                cls.ToCString());
        }
        return function;
      }
    }
    case kClosure: {
      ReadObject();  // Skip enclosing member.
      const intptr_t closure_index = reader_.ReadUInt();
      return closures_->At(closure_index);
    }
    case kName: {
      if ((flags & kFlagIsPublic) == 0) {
        const Library& library = Library::CheckedHandle(Z, ReadObject());
        ASSERT(!library.IsNull());
        auto& name = String::Handle(Z, ReadString(/* is_canonical = */ false));
        name = library.PrivateName(name);
        return name.ptr();
      }
      return ReadString();
    }
    case kTypeArguments: {
      return ReadTypeArguments();
    }
    case kConstObject: {
      const intptr_t tag = flags / kFlagBit0;
      return ReadConstObject(tag);
    }
    case kArgDesc: {
      const intptr_t num_arguments = reader_.ReadUInt();
      const intptr_t num_type_args =
          ((flags & kFlagHasTypeArgs) != 0) ? reader_.ReadUInt() : 0;
      if ((flags & kFlagHasNamedArgs) == 0) {
        return ArgumentsDescriptor::NewBoxed(num_type_args, num_arguments);
      } else {
        const intptr_t num_arg_names = reader_.ReadListLength();
        const Array& array = Array::Handle(Z, Array::New(num_arg_names));
        String& name = String::Handle(Z);
        for (intptr_t i = 0; i < num_arg_names; ++i) {
          name ^= ReadObject();
          array.SetAt(i, name);
        }
        return ArgumentsDescriptor::NewBoxed(num_type_args, num_arguments,
                                             array);
      }
    }
    case kScript: {
      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()) {
        if (Function::Cast(parent).IsFactory()) {
          // For factory constructors VM uses type parameters of a class
          // instead of constructor's type parameters.
          parent = Function::Cast(parent).Owner();
          type =
              Class::Cast(parent).TypeParameterAt(index_in_parent, nullability);
        } else {
          type = Function::Cast(parent).TypeParameterAt(index_in_parent,
                                                        nullability);
        }
      } else if (parent.IsNull()) {
        ASSERT(!enclosing_function_types_.is_empty());
        for (intptr_t i = enclosing_function_types_.length() - 1; i >= 0; --i) {
          parent = enclosing_function_types_[i]->ptr();
          ASSERT(index_in_parent <
                 FunctionType::Cast(parent).NumTypeArguments());
          if (index_in_parent >=
              FunctionType::Cast(parent).NumParentTypeArguments()) {
            break;
          }
        }
        type = FunctionType::Cast(parent).TypeParameterAt(
            index_in_parent -
                FunctionType::Cast(parent).NumParentTypeArguments(),
            nullability);
      } else {
        UNREACHABLE();
      }
      return ClassFinalizer::FinalizeType(type, ClassFinalizer::kCanonicalize);
    }
    case kGenericType: {
      const Class& cls = Class::CheckedHandle(Z, ReadObject());
      if (!cls.is_declaration_loaded()) {
        LoadReferencedClass(cls);
      }
      const TypeArguments& type_arguments =
          TypeArguments::CheckedHandle(Z, ReadObject());
      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 num_fields = reader_.ReadListLength();
  if ((num_fields == 0) && !cls.is_enum_class()) {
    return;
  }
  const Array& fields = Array::Handle(
      Z, Array::New(num_fields + (cls.is_enum_class() ? 1 : 0), Heap::kOld));
  String& name = String::Handle(Z);
  Object& script_class = Object::Handle(Z);
  AbstractType& type = AbstractType::Handle(Z);
  Field& field = Field::Handle(Z);
  Object& value = Object::Handle(Z);
  Function& function = Function::Handle(Z);

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

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

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

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

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

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

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

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

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

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

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

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

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

    fields.SetAt(i, field);
  }

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

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

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

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

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

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

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

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

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

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

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

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

  name = cls.ScrubbedName();

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

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

    name ^= ReadObject();

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

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

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

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

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

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

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

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

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

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

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

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

    intptr_t param_index = 0;
    if (!is_static) {
      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;
    } else if (is_factory) {
      signature.SetParameterTypeAt(param_index, AbstractType::dynamic_type());
      NOT_IN_PRECOMPILED(function.SetParameterNameAt(
          param_index, Symbols::TypeArgumentsParameter()));
      ++param_index;
    }

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

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

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

    if (is_native) {
      name ^= ReadObject();
      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) {
      ASSERT(!function.is_abstract());
      BytecodeLoader* loader = thread_->bytecode_loader();
      ASSERT(loader != nullptr);
      loader->SetExpressionEvaluationFunction(function);
      // Read bytecode of expression evaluation function within FunctionScope.
      // Replace class of the function in scope as we're going to look for
      // expression evaluation function in a real class.
      if (!cls.IsTopLevel()) {
        scoped_function_class_ = loader->GetExpressionEvaluationRealClass();
      }
      ReadCode(function, 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;

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

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

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

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

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

  cls.set_has_pragma(has_pragma);

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

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

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

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

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

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

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

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

void BytecodeReaderHelper::ReadLibraryDeclaration(const Library& library,
                                                  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)
