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

#include "vm/kernel_loader.h"

#include <string.h>

#include <memory>

#include "vm/closure_functions_cache.h"
#include "vm/compiler/backend/flow_graph_compiler.h"
#include "vm/compiler/frontend/constant_reader.h"
#include "vm/compiler/frontend/kernel_translation_helper.h"
#include "vm/dart_api_impl.h"
#include "vm/flags.h"
#include "vm/heap/heap.h"
#include "vm/kernel_binary.h"
#include "vm/longjump.h"
#include "vm/object_store.h"
#include "vm/parser.h"
#include "vm/reusable_handles.h"
#include "vm/service_isolate.h"
#include "vm/symbols.h"
#include "vm/thread.h"

namespace dart {
namespace kernel {

#define Z (zone_)
#define I (isolate_)
#define IG (thread_->isolate_group())
#define T (type_translator_)
#define H (translation_helper_)

static const char* const kVMServiceIOLibraryUri = "dart:vmservice_io";

class SimpleExpressionConverter {
 public:
  SimpleExpressionConverter(TranslationHelper* translation_helper,
                            KernelReaderHelper* reader_helper)
      : translation_helper_(*translation_helper),
        zone_(translation_helper_.zone()),
        simple_value_(nullptr),
        helper_(reader_helper) {}

  bool IsSimple(intptr_t kernel_offset) {
    AlternativeReadingScope alt(&helper_->reader_, kernel_offset);
    uint8_t payload = 0;
    Tag tag = helper_->ReadTag(&payload);  // read tag.
    switch (tag) {
      case kBigIntLiteral: {
        helper_->ReadPosition();
        const String& literal_str =
            H.DartString(helper_->ReadStringReference(),
                         Heap::kOld);  // read index into string table.
        simple_value_ = &Integer::ZoneHandle(Z, Integer::New(literal_str));
        if (simple_value_->IsNull()) {
          H.ReportError("Integer literal %s is out of range",
                        literal_str.ToCString());
          UNREACHABLE();
        }
        *simple_value_ = H.Canonicalize(*simple_value_);
        return true;
      }
      case kStringLiteral:
        helper_->ReadPosition();
        simple_value_ = &H.DartSymbolPlain(
            helper_->ReadStringReference());  // read index into string table.
        return true;
      case kSpecializedIntLiteral:
        helper_->ReadPosition();
        simple_value_ =
            &Integer::ZoneHandle(Z, Integer::New(static_cast<int32_t>(payload) -
                                                     SpecializedIntLiteralBias,
                                                 Heap::kOld));
        *simple_value_ = H.Canonicalize(*simple_value_);
        return true;
      case kNegativeIntLiteral:
        helper_->ReadPosition();
        simple_value_ = &Integer::ZoneHandle(
            Z, Integer::New(-static_cast<int64_t>(helper_->ReadUInt()),
                            Heap::kOld));  // read value.
        *simple_value_ = H.Canonicalize(*simple_value_);
        return true;
      case kPositiveIntLiteral:
        helper_->ReadPosition();
        simple_value_ = &Integer::ZoneHandle(
            Z, Integer::New(static_cast<int64_t>(helper_->ReadUInt()),
                            Heap::kOld));  // read value.
        *simple_value_ = H.Canonicalize(*simple_value_);
        return true;
      case kDoubleLiteral:
        helper_->ReadPosition();
        simple_value_ = &Double::ZoneHandle(
            Z, Double::New(helper_->ReadDouble(), Heap::kOld));  // read value.
        *simple_value_ = H.Canonicalize(*simple_value_);
        return true;
      case kTrueLiteral:
        helper_->ReadPosition();
        simple_value_ = &Bool::Handle(Z, Bool::Get(true).ptr());
        return true;
      case kFalseLiteral:
        helper_->ReadPosition();
        simple_value_ = &Bool::Handle(Z, Bool::Get(false).ptr());
        return true;
      case kNullLiteral:
        helper_->ReadPosition();
        simple_value_ = &Instance::ZoneHandle(Z, Instance::null());
        return true;
      default:
        return false;
    }
  }

  const Instance& SimpleValue() { return *simple_value_; }
  Zone* zone() const { return zone_; }

 private:
  TranslationHelper& translation_helper_;
  Zone* zone_;
  Instance* simple_value_;
  KernelReaderHelper* helper_;

  DISALLOW_COPY_AND_ASSIGN(SimpleExpressionConverter);
};

ArrayPtr KernelLoader::MakeFieldsArray() {
  const intptr_t len = fields_.length();
  const Array& res = Array::Handle(zone_, Array::New(len, Heap::kOld));
  for (intptr_t i = 0; i < len; i++) {
    res.SetAt(i, *fields_[i]);
  }
  return res.ptr();
}

ArrayPtr KernelLoader::MakeFunctionsArray() {
  const intptr_t len = functions_.length();
  const Array& res = Array::Handle(zone_, Array::New(len, Heap::kOld));
  for (intptr_t i = 0; i < len; i++) {
    res.SetAt(i, *functions_[i]);
  }
  return res.ptr();
}

LibraryPtr BuildingTranslationHelper::LookupLibraryByKernelLibrary(
    NameIndex library,
    bool required) {
  return loader_->LookupLibrary(library);
}

ClassPtr BuildingTranslationHelper::LookupClassByKernelClass(NameIndex klass,
                                                             bool required) {
#if defined(DEBUG)
  LibraryLookupHandleScope library_lookup_handle_scope(library_lookup_handle_);
#endif  // defined(DEBUG)
  library_lookup_handle_ = loader_->LookupLibraryFromClass(klass);
  return loader_->LookupClass(library_lookup_handle_, klass);
}

LibraryIndex::LibraryIndex(const TypedDataView& kernel_data)
    : reader_(kernel_data) {
  intptr_t data_size = reader_.size();

  procedure_count_ = reader_.ReadUInt32At(data_size - 4);
  procedure_index_offset_ = data_size - 4 - (procedure_count_ + 1) * 4;

  class_count_ = reader_.ReadUInt32At(procedure_index_offset_ - 4);
  class_index_offset_ = procedure_index_offset_ - 4 - (class_count_ + 1) * 4;

  source_references_offset_ = -1;
  source_references_offset_ = reader_.ReadUInt32At(class_index_offset_ - 4);
}

ClassIndex::ClassIndex(const TypedDataBase& library_kernel_data,
                       intptr_t class_offset,
                       intptr_t class_size)
    : reader_(library_kernel_data) {
  Init(class_offset, class_size);
}

void ClassIndex::Init(intptr_t class_offset, intptr_t class_size) {
  procedure_count_ = reader_.ReadUInt32At(class_offset + class_size - 4);
  procedure_index_offset_ =
      class_offset + class_size - 4 - (procedure_count_ + 1) * 4;
}

using UriToSourceTable = DirectChainedHashMap<UriToSourceTableTrait>;

KernelLoader::KernelLoader(Program* program,
                           UriToSourceTable* uri_to_source_table)
    : program_(program),
      thread_(Thread::Current()),
      zone_(thread_->zone()),
      no_active_isolate_scope_(),
      patch_classes_(Array::Handle(zone_)),
      active_class_(),
      library_kernel_offset_(-1),  // Set to the correct value in LoadLibrary
      correction_offset_(-1),      // Set to the correct value in LoadLibrary
      loading_native_wrappers_library_(false),
      library_kernel_data_(TypedDataView::Handle(zone_)),
      kernel_program_info_(KernelProgramInfo::Handle(zone_)),
      translation_helper_(this, thread_, Heap::kOld),
      helper_(zone_,
              &translation_helper_,
              program_->binary(),
              /*data_program_offset=*/0),
      constant_reader_(&helper_, &active_class_),
      type_translator_(&helper_,
                       &constant_reader_,
                       &active_class_,
                       /* finalize= */ false),
      inferred_type_metadata_helper_(&helper_, &constant_reader_),
      static_field_value_(Object::Handle(Z)),
      name_index_handle_(Smi::Handle(Z)),
      expression_evaluation_library_(Library::Handle(Z)) {
  if (!program->is_single_program()) {
    FATAL(
        "Trying to load a concatenated dill file at a time where that is "
        "not allowed");
  }
  InitializeFields(uri_to_source_table);
}

void KernelLoader::ReadObfuscationProhibitions() {
  ObfuscationProhibitionsMetadataHelper helper(&helper_);
  helper.ReadProhibitions();
}

void KernelLoader::ReadLoadingUnits() {
  LoadingUnitsMetadataHelper helper(&helper_);
  helper.ReadLoadingUnits();
}

Object& KernelLoader::LoadEntireProgram(Program* program,
                                        bool process_pending_classes) {
  Thread* thread = Thread::Current();

  TIMELINE_DURATION(thread, Isolate, "LoadKernel");

  if (program->is_single_program()) {
    KernelLoader loader(program, /*uri_to_source_table=*/nullptr);
    return Object::Handle(loader.LoadProgram(process_pending_classes));
  }

  GrowableArray<intptr_t> subprogram_file_starts;
  {
    kernel::Reader reader(program->binary());
    index_programs(&reader, &subprogram_file_starts);
  }

  Zone* zone = thread->zone();
  Library& library = Library::Handle(zone);
  intptr_t subprogram_count = subprogram_file_starts.length() - 1;

  // First index all source tables.
  UriToSourceTable uri_to_source_table;
  UriToSourceTableEntry wrapper;
  Thread* thread_ = Thread::Current();
  Zone* zone_ = thread_->zone();
  for (intptr_t i = subprogram_count - 1; i >= 0; --i) {
    intptr_t subprogram_start = subprogram_file_starts.At(i);
    intptr_t subprogram_end = subprogram_file_starts.At(i + 1);
    const auto& component = TypedDataBase::Handle(
        program->binary().ViewFromTo(subprogram_start, subprogram_end));
    TranslationHelper translation_helper(thread);
    KernelReaderHelper helper_(zone_, &translation_helper, component, 0);
    const intptr_t source_table_size = helper_.SourceTableSize();
    for (intptr_t index = 0; index < source_table_size; ++index) {
      const String& uri_string = helper_.SourceTableUriFor(index);
      wrapper.uri = &uri_string;
      TypedData& line_starts =
          TypedData::Handle(Z, helper_.GetLineStartsFor(index));
      if (line_starts.Length() == 0) continue;
      const String& script_source = helper_.GetSourceFor(index);
      wrapper.uri = &uri_string;
      UriToSourceTableEntry* pair = uri_to_source_table.LookupValue(&wrapper);
      if (pair != nullptr) {
        // At least two entries with content. Unless the content is the same
        // that's not valid.
        const bool src_differ = pair->sources->CompareTo(script_source) != 0;
        const bool line_starts_differ =
            !pair->line_starts->CanonicalizeEquals(line_starts);
        if (src_differ || line_starts_differ) {
          FATAL(
              "Invalid kernel binary: Contains at least two source entries "
              "that do not agree. URI '%s', difference: %s. Subprogram count: "
              "%" Pd ".",
              uri_string.ToCString(),
              src_differ && line_starts_differ
                  ? "src and line starts"
                  : (src_differ ? "src" : "line starts"),
              subprogram_count);
        }
      } else {
        UriToSourceTableEntry* tmp = new UriToSourceTableEntry();
        tmp->uri = &uri_string;
        tmp->sources = &script_source;
        tmp->line_starts = &line_starts;
        uri_to_source_table.Insert(tmp);
      }
    }
  }

  // Create "fake programs" for each sub-program.
  for (intptr_t i = subprogram_count - 1; i >= 0; --i) {
    intptr_t subprogram_start = subprogram_file_starts.At(i);
    intptr_t subprogram_end = subprogram_file_starts.At(i + 1);
    const auto& component = TypedDataBase::Handle(
        program->binary().ViewFromTo(subprogram_start, subprogram_end));
    Reader reader(component);
    const char* error = nullptr;
    std::unique_ptr<Program> subprogram = Program::ReadFrom(&reader, &error);
    if (subprogram == nullptr) {
      FATAL("Failed to load kernel file: %s", error);
    }
    ASSERT(subprogram->is_single_program());
    KernelLoader loader(subprogram.get(), &uri_to_source_table);
    Object& load_result = Object::Handle(loader.LoadProgram(false));
    if (load_result.IsError()) return load_result;

    if (load_result.IsLibrary()) {
      library ^= load_result.ptr();
    }
  }

  if (process_pending_classes && !ClassFinalizer::ProcessPendingClasses()) {
    // Class finalization failed -> sticky error would be set.
    return Error::Handle(thread->StealStickyError());
  }

  return library;
}

void KernelLoader::index_programs(
    kernel::Reader* reader,
    GrowableArray<intptr_t>* subprogram_file_starts) {
  // Dill files can be concatenated (e.g. cat a.dill b.dill > c.dill), so we
  // need to first index the (possibly combined) file.
  // First entry becomes last entry.
  // Last entry is for ease of calculating size of last subprogram.
  subprogram_file_starts->Add(reader->size());
  reader->set_offset(reader->size() - 4);
  while (reader->offset() > 0) {
    intptr_t size = reader->ReadUInt32();
    intptr_t start = reader->offset() - size;
    if (start < 0) {
      FATAL("Invalid kernel binary: Indicated size is invalid.");
    }
    subprogram_file_starts->Add(start);
    reader->set_offset(start - 4);
  }
  subprogram_file_starts->Reverse();
}

StringPtr KernelLoader::FindSourceForScript(const uint8_t* kernel_buffer,
                                            intptr_t kernel_buffer_length,
                                            const String& uri) {
  const auto& binary = ExternalTypedData::Handle(ExternalTypedData::New(
      kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(kernel_buffer),
      kernel_buffer_length, Heap::kNew));

  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  TranslationHelper translation_helper(thread);
  KernelReaderHelper reader(zone, &translation_helper, binary, 0);
  intptr_t source_table_size = reader.SourceTableSize();
  for (intptr_t i = 0; i < source_table_size; ++i) {
    const String& source_uri = reader.SourceTableUriFor(i);
    if (source_uri.EndsWith(uri)) {
      return reader.GetSourceFor(i).ptr();
    }
  }
  return String::null();
}

void KernelLoader::InitializeFields(UriToSourceTable* uri_to_source_table) {
  const intptr_t source_table_size = helper_.SourceTableSize();
  const Array& scripts =
      Array::Handle(Z, Array::New(source_table_size, Heap::kOld));

  const auto& binary = program_->binary();

  // Copy the Kernel string offsets out of the binary and into the VM's heap.
  ASSERT(program_->string_table_offset() >= 0);
  Reader reader(binary);
  reader.set_offset(program_->string_table_offset());
  intptr_t count = reader.ReadUInt() + 1;
  const auto& offsets = TypedData::Handle(
      Z, TypedData::New(kTypedDataUint32ArrayCid, count, Heap::kOld));
  offsets.SetUint32(0, 0);
  intptr_t end_offset = 0;
  for (intptr_t i = 1; i < count; ++i) {
    end_offset = reader.ReadUInt();
    offsets.SetUint32(i << 2, end_offset);
  }

  // Create view of the string data.
  const auto& string_data = TypedDataView::Handle(
      reader.ViewFromTo(reader.offset(), reader.offset() + end_offset));

  // Create a view of the constants table.
  const auto& constants_table = TypedDataView::Handle(reader.ViewFromTo(
      program_->constant_table_offset(), program_->name_table_offset()));

  // Copy the canonical names into the VM's heap.  Encode them as unsigned, so
  // the parent indexes are adjusted when extracted.
  reader.set_offset(program_->name_table_offset());
  count = reader.ReadUInt() * 2;
  TypedData& names = TypedData::Handle(
      Z, TypedData::New(kTypedDataUint32ArrayCid, count, Heap::kOld));
  for (intptr_t i = 0; i < count; ++i) {
    names.SetUint32(i << 2, reader.ReadUInt());
  }

  // Create view of metadata payloads.
  const auto& metadata_payloads = TypedDataView::Handle(
      reader.ViewFromTo(program_->metadata_payloads_offset(),
                        program_->metadata_mappings_offset()));

  ASSERT(Utils::IsAligned(metadata_payloads.DataAddr(0), kWordSize));

  // Create view of metadata mappings.
  const auto& metadata_mappings = TypedDataView::Handle(reader.ViewFromTo(
      program_->metadata_mappings_offset(), program_->string_table_offset()));

#if defined(DEBUG)
  MetadataHelper::VerifyMetadataMappings(metadata_mappings);
#endif

  const Array& libraries_cache =
      Array::Handle(Z, HashTables::New<UnorderedHashMap<SmiTraits>>(
                           program_->library_count(), Heap::kOld));

  const intptr_t kClassesPerLibraryGuess = 5;
  const Array& classes_cache = Array::Handle(
      Z, HashTables::New<UnorderedHashMap<SmiTraits>>(
             kClassesPerLibraryGuess * program_->library_count(), Heap::kOld));

  kernel_program_info_ = KernelProgramInfo::New(
      binary, string_data, metadata_payloads, metadata_mappings,
      constants_table, offsets, names, scripts, libraries_cache, classes_cache);

  H.InitFromKernelProgramInfo(kernel_program_info_);

  Script& script = Script::Handle(Z);
  for (intptr_t index = 0; index < source_table_size; ++index) {
    script = LoadScriptAt(index, uri_to_source_table);
    scripts.SetAt(index, script);
  }
}

KernelLoader::KernelLoader(const KernelProgramInfo& kernel_program_info,
                           const TypedDataBase& kernel_data,
                           intptr_t data_program_offset)
    : program_(nullptr),
      thread_(Thread::Current()),
      zone_(thread_->zone()),
      no_active_isolate_scope_(),
      patch_classes_(Array::Handle(zone_)),
      library_kernel_offset_(data_program_offset),
      correction_offset_(0),
      loading_native_wrappers_library_(false),
      library_kernel_data_(TypedDataView::Handle(zone_)),
      kernel_program_info_(
          KernelProgramInfo::Handle(zone_, kernel_program_info.ptr())),
      translation_helper_(this, thread_, Heap::kOld),
      helper_(zone_, &translation_helper_, kernel_data, 0),
      constant_reader_(&helper_, &active_class_),
      type_translator_(&helper_,
                       &constant_reader_,
                       &active_class_,
                       /* finalize= */ false),
      inferred_type_metadata_helper_(&helper_, &constant_reader_),
      static_field_value_(Object::Handle(Z)),
      name_index_handle_(Smi::Handle(Z)),
      expression_evaluation_library_(Library::Handle(Z)) {
  ASSERT(T.active_class_ == &active_class_);
  T.finalize_ = false;
  H.InitFromKernelProgramInfo(kernel_program_info_);
}

bool KernelLoader::IsClassName(NameIndex name,
                               const String& library,
                               const String& klass) {
  ASSERT(H.IsClass(name));
  StringIndex class_name_index = H.CanonicalNameString(name);

  if (!H.StringEquals(class_name_index, klass.ToCString())) {
    return false;
  }
  ASSERT(H.IsLibrary(H.CanonicalNameParent(name)));
  StringIndex library_name_index =
      H.CanonicalNameString(H.CanonicalNameParent(name));
  return H.StringEquals(library_name_index, library.ToCString());
}

ObjectPtr KernelLoader::LoadProgram(bool process_pending_classes) {
  SafepointWriteRwLocker ml(thread_, thread_->isolate_group()->program_lock());
  ASSERT(kernel_program_info_.constants() == Array::null());

  if (!program_->is_single_program()) {
    FATAL(
        "Trying to load a concatenated dill file at a time where that is "
        "not allowed");
  }

  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    // Note that `problemsAsJson` on Component is implicitly skipped.
    const intptr_t length = program_->library_count();
    for (intptr_t i = 0; i < length; i++) {
      LoadLibrary(i);
    }

    // Finalize still pending classes if requested.
    if (process_pending_classes) {
      if (!ClassFinalizer::ProcessPendingClasses()) {
        // Class finalization failed -> sticky error would be set.
        return H.thread()->StealStickyError();
      }
    }

    // Sets the constants array to an empty array with the length equal to
    // the number of constants. The array gets filled lazily while reading
    // constants.
    ASSERT(kernel_program_info_.constants_table() != ExternalTypedData::null());
    ConstantReader constant_reader(&helper_, &active_class_);
    const intptr_t num_consts = constant_reader.NumConstants();
    const Array& array = Array::Handle(Z, Array::New(num_consts, Heap::kOld));
    for (intptr_t i = 0; i < num_consts; i++) {
      array.SetAt(i, Object::sentinel());
    }
    kernel_program_info_.set_constants(array);
    H.SetConstants(array);  // for caching

    NameIndex main = program_->main_method();
    if (main != -1) {
      NameIndex main_library = H.EnclosingName(main);
      return LookupLibrary(main_library);
    }

    return Library::null();
  }

  // Either class finalization failed or we caught a compile error.
  // In both cases sticky error would be set.
  return Thread::Current()->StealStickyError();
}

void KernelLoader::LoadLibrary(const Library& library) {
  // This will be invoked by VM bootstrapping code.
  SafepointWriteRwLocker ml(thread_, thread_->isolate_group()->program_lock());

  ASSERT(!library.Loaded());

  const auto& uri = String::Handle(Z, library.url());
  const intptr_t num_libraries = program_->library_count();
  for (intptr_t i = 0; i < num_libraries; ++i) {
    const String& library_uri = LibraryUri(i);
    if (library_uri.Equals(uri)) {
      LoadLibrary(i);
      return;
    }
  }
}

ObjectPtr KernelLoader::LoadExpressionEvaluationFunction(
    const String& library_url,
    const String& klass) {
  // Find the original context, i.e. library/class, in which the evaluation will
  // happen.
  const Library& real_library =
      Library::Handle(Z, Library::LookupLibrary(thread_, library_url));
  ASSERT(!real_library.IsNull());
  const Class& real_class = Class::Handle(
      Z, klass.IsNull() ? real_library.toplevel_class()
                        : real_library.LookupClassAllowPrivate(klass));
  ASSERT(!real_class.IsNull());

  const intptr_t num_cids = IG->class_table()->NumCids();
  const intptr_t num_libs =
      GrowableObjectArray::Handle(IG->object_store()->libraries()).Length();

  // Load the "evaluate:source" expression evaluation library.
  ASSERT(expression_evaluation_library_.IsNull());
  ASSERT(H.GetExpressionEvaluationClass().IsNull());
  ASSERT(H.GetExpressionEvaluationFunction().IsNull());
  H.SetExpressionEvaluationRealClass(real_class);
  const Object& result = Object::Handle(Z, LoadProgram(true));
  if (result.IsError()) {
    return result.ptr();
  }
  const Function& function = H.GetExpressionEvaluationFunction();
  ASSERT(!function.IsNull());
  ASSERT(
      GrowableObjectArray::Handle(IG->object_store()->libraries()).Length() ==
      num_libs);
  ASSERT(IG->class_table()->NumCids() == num_cids);

  // Make the expression evaluation function have the right script,
  // kernel data and parent.
  const auto& eval_script = Script::Handle(Z, function.script());
  ASSERT(!expression_evaluation_library_.IsNull());
  function.SetKernelLibraryAndEvalScript(
      eval_script, kernel_program_info_,
      expression_evaluation_library_.kernel_library_index());

  function.set_owner(real_class);

  ASSERT(real_class.is_finalized());
  // The owner class has already been marked as finalized so the signature of
  // this added function must be finalized here, since finalization of member
  // types will not be called anymore.
  FunctionType& signature = FunctionType::Handle(Z, function.signature());
  if (!function.is_static()) {
    // Patch the illegal receiver type (type class with kIllegalCid) to dynamic.
    signature.SetParameterTypeAt(0, Object::dynamic_type());
  }
  signature ^= ClassFinalizer::FinalizeType(signature);
  function.SetSignature(signature);

  return function.ptr();
}

void KernelLoader::FindModifiedLibraries(Program* program,
                                         IsolateGroup* isolate_group,
                                         BitVector* modified_libs,
                                         bool force_reload,
                                         bool* is_empty_program,
                                         intptr_t* p_num_classes,
                                         intptr_t* p_num_procedures) {
  LongJumpScope jump;
  Zone* zone = Thread::Current()->zone();
  if (setjmp(*jump.Set()) == 0) {
    if (force_reload) {
      // If a reload is being forced we mark all libraries as having
      // been modified.
      const auto& libs = GrowableObjectArray::Handle(
          isolate_group->object_store()->libraries());
      intptr_t num_libs = libs.Length();
      Library& lib = dart::Library::Handle(zone);
      for (intptr_t i = 0; i < num_libs; i++) {
        lib ^= libs.At(i);
        if (!lib.is_dart_scheme()) {
          modified_libs->Add(lib.index());
        }
      }
      return;
    }

    if (p_num_classes != nullptr) {
      *p_num_classes = 0;
    }
    if (p_num_procedures != nullptr) {
      *p_num_procedures = 0;
    }

    // Now go through all the libraries that are present in the incremental
    // kernel files, these will constitute the modified libraries.
    *is_empty_program = true;
    if (program->is_single_program()) {
      KernelLoader loader(program, /*uri_to_source_table=*/nullptr);
      loader.walk_incremental_kernel(modified_libs, is_empty_program,
                                     p_num_classes, p_num_procedures);
    }

    GrowableArray<intptr_t> subprogram_file_starts;
    {
      kernel::Reader reader(program->binary());
      index_programs(&reader, &subprogram_file_starts);
    }

    // Create "fake programs" for each sub-program.
    intptr_t subprogram_count = subprogram_file_starts.length() - 1;
    for (intptr_t i = 0; i < subprogram_count; ++i) {
      intptr_t subprogram_start = subprogram_file_starts.At(i);
      intptr_t subprogram_end = subprogram_file_starts.At(i + 1);
      const auto& component = TypedDataBase::Handle(
          program->binary().ViewFromTo(subprogram_start, subprogram_end));
      Reader reader(component);
      const char* error = nullptr;
      std::unique_ptr<Program> subprogram = Program::ReadFrom(&reader, &error);
      if (subprogram == nullptr) {
        FATAL("Failed to load kernel file: %s", error);
      }
      ASSERT(subprogram->is_single_program());
      KernelLoader loader(subprogram.get(), /*uri_to_source_table=*/nullptr);
      loader.walk_incremental_kernel(modified_libs, is_empty_program,
                                     p_num_classes, p_num_procedures);
    }
  }
}

void KernelLoader::walk_incremental_kernel(BitVector* modified_libs,
                                           bool* is_empty_program,
                                           intptr_t* p_num_classes,
                                           intptr_t* p_num_procedures) {
  intptr_t length = program_->library_count();
  *is_empty_program = *is_empty_program && (length == 0);
  bool collect_library_stats =
      p_num_classes != nullptr || p_num_procedures != nullptr;
  intptr_t num_classes = 0;
  intptr_t num_procedures = 0;
  Library& lib = Library::Handle(Z);
  for (intptr_t i = 0; i < length; i++) {
    intptr_t kernel_offset = library_offset(i);
    helper_.SetOffset(kernel_offset);
    LibraryHelper library_helper(&helper_);
    library_helper.ReadUntilIncluding(LibraryHelper::kCanonicalName);
    lib = LookupLibraryOrNull(library_helper.canonical_name_);
    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());
    }
    if (collect_library_stats) {
      intptr_t library_end = library_offset(i + 1);
      library_kernel_data_ =
          helper_.reader_.ViewFromTo(kernel_offset, library_end);
      LibraryIndex library_index(library_kernel_data_);
      num_classes += library_index.class_count();
      num_procedures += library_index.procedure_count();
    }
  }
  if (p_num_classes != nullptr) {
    *p_num_classes += num_classes;
  }
  if (p_num_procedures != nullptr) {
    *p_num_procedures += num_procedures;
  }
}

void KernelLoader::ReadInferredType(const Field& field,
                                    intptr_t kernel_offset) {
  const InferredTypeMetadata type =
      inferred_type_metadata_helper_.GetInferredType(kernel_offset,
                                                     /*read_constant=*/false);
  if (type.IsTrivial()) {
    return;
  }
  field.set_guarded_cid(type.cid);
  field.set_is_nullable(type.IsNullable());
  field.set_guarded_list_length(Field::kNoFixedLength);
  if (FLAG_precompiled_mode) {
    field.set_is_unboxed(!field.is_late() && !field.is_static() &&
                         !field.is_nullable() &&
                         ((field.guarded_cid() == kDoubleCid &&
                           FlowGraphCompiler::SupportsUnboxedDoubles()) ||
                          (field.guarded_cid() == kFloat32x4Cid &&
                           FlowGraphCompiler::SupportsUnboxedSimd128()) ||
                          (field.guarded_cid() == kFloat64x2Cid &&
                           FlowGraphCompiler::SupportsUnboxedSimd128()) ||
                          type.IsInt()));
  }
}

void KernelLoader::CheckForInitializer(const Field& field) {
  if (helper_.PeekTag() == kSomething) {
    field.set_has_initializer(true);
    SimpleExpressionConverter converter(&H, &helper_);
    const bool has_simple_initializer =
        converter.IsSimple(helper_.ReaderOffset() + 1);
    if (!has_simple_initializer ||
        (!field.is_static() && !converter.SimpleValue().IsNull())) {
      field.set_has_nontrivial_initializer(true);
    }
    return;
  }
  field.set_has_initializer(false);
  field.set_has_nontrivial_initializer(false);
}

LibraryPtr KernelLoader::LoadLibrary(intptr_t index) {
  if (!program_->is_single_program()) {
    FATAL(
        "Trying to load a concatenated dill file at a time where that is "
        "not allowed");
  }

  // Read library index.
  library_kernel_offset_ = library_offset(index);
  correction_offset_ = library_kernel_offset_;
  intptr_t library_end = library_offset(index + 1);
  intptr_t library_size = library_end - library_kernel_offset_;

  // NOTE: Since |helper_| is used to load the overall kernel program,
  // it's reader's offset is an offset into the overall kernel program.
  // Hence, when setting the kernel offsets of field and functions, one
  // has to subtract the library's kernel offset from the reader's
  // offset.
  helper_.SetOffset(library_kernel_offset_);

  LibraryHelper library_helper(&helper_);
  library_helper.ReadUntilIncluding(LibraryHelper::kCanonicalName);
  if (!FLAG_precompiled_mode && !IG->should_load_vmservice()) {
    StringIndex lib_name_index =
        H.CanonicalNameString(library_helper.canonical_name_);
    if (H.StringEquals(lib_name_index, kVMServiceIOLibraryUri)) {
      // We are not the service isolate and we are not generating an AOT
      // snapshot so we skip loading 'dart:vmservice_io'.
      skip_vmservice_library_ = library_helper.canonical_name_;
      ASSERT(H.IsLibrary(skip_vmservice_library_));
      return Library::null();
    }
  }

  Library& library =
      Library::Handle(Z, LookupLibrary(library_helper.canonical_name_));

  if (library.Loaded()) return library.ptr();

  library.set_is_nnbd(library_helper.IsNonNullableByDefault());
  const NNBDCompiledMode mode =
      library_helper.GetNonNullableByDefaultCompiledMode();
  if (mode == NNBDCompiledMode::kInvalid) {
    H.ReportError(
        "Library '%s' was compiled in an unsupported mixed mode between sound "
        "null safety and not sound null safety.",
        String::Handle(library.url()).ToCString());
  }
  if (mode == NNBDCompiledMode::kWeak) {
    H.ReportError(
        "Library '%s' was compiled without sound null safety (in weak mode) "
        "and it "
        "cannot be used with --sound-null-safety at runtime",
        String::Handle(library.url()).ToCString());
  }
  library.set_nnbd_compiled_mode(mode);

  library_kernel_data_ = helper_.reader_.ViewFromTo(
      library_kernel_offset_, library_kernel_offset_ + library_size);
  library.set_kernel_library_index(index);
  library.set_kernel_program_info(kernel_program_info_);

  const intptr_t start_offset =
      kernel_program_info_.KernelLibraryStartOffset(index);
  const intptr_t end_offset =
      kernel_program_info_.KernelLibraryEndOffset(index);
  library_kernel_data_ = helper_.reader_.ViewFromTo(start_offset, end_offset);
  LibraryIndex library_index(library_kernel_data_);
  intptr_t class_count = library_index.class_count();

  library_helper.ReadUntilIncluding(LibraryHelper::kName);
  library.SetName(H.DartSymbolObfuscate(library_helper.name_index_));

  // The bootstrapper will take care of creating the native wrapper classes, but
  // we will add the synthetic constructors to them here.
  if (library.name() ==
      Symbols::Symbol(Symbols::kDartNativeWrappersLibNameId).ptr()) {
    ASSERT(library.LoadInProgress());
    loading_native_wrappers_library_ = true;
  } else {
    loading_native_wrappers_library_ = false;
    library.SetLoadInProgress();
  }

  if (library.url() == Symbols::vm_ffi_native_assets().ptr()) {
    const auto& native_assets_library =
        Library::Handle(IG->object_store()->native_assets_library());
    ASSERT(native_assets_library.IsNull());
    IG->object_store()->set_native_assets_library(library);
  }

  library_helper.ReadUntilIncluding(LibraryHelper::kSourceUriIndex);
  const Script& script =
      Script::Handle(Z, ScriptAt(library_helper.source_uri_index_));

  library_helper.ReadUntilExcluding(LibraryHelper::kAnnotations);
  intptr_t annotations_kernel_offset =
      helper_.ReaderOffset() - correction_offset_;
  const intptr_t annotation_count =
      helper_.ReadListLength();  // read list length.
  for (intptr_t i = 0; i < annotation_count; ++i) {
    helper_.SkipExpression();  // read ith annotation.
  }
  library_helper.SetJustRead(LibraryHelper::kAnnotations);

  // Setup toplevel class (which contains library fields/procedures).

  // We do not register expression evaluation classes 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.
  const bool register_class =
      library.ptr() != expression_evaluation_library_.ptr();

  Class& toplevel_class =
      Class::Handle(Z, Class::New(library, Symbols::TopLevel(), script,
                                  TokenPosition::kNoSource, register_class));
  toplevel_class.set_is_abstract();
  toplevel_class.set_is_declaration_loaded();
  toplevel_class.set_is_type_finalized();
  toplevel_class.set_num_type_arguments_unsafe(0);
  library.set_toplevel_class(toplevel_class);

  library_helper.ReadUntilExcluding(LibraryHelper::kDependencies);
  LoadLibraryImportsAndExports(&library, toplevel_class);
  library_helper.SetJustRead(LibraryHelper::kDependencies);

  // Everything up til the classes are skipped implicitly, and library_helper
  // is no longer used.

  const GrowableObjectArray& classes =
      GrowableObjectArray::Handle(Z, IG->object_store()->pending_classes());

  // Load all classes.
  intptr_t next_class_offset = library_index.ClassOffset(0);
  Class& klass = Class::Handle(Z);
  for (intptr_t i = 0; i < class_count; ++i) {
    helper_.SetOffset(next_class_offset);
    next_class_offset = library_index.ClassOffset(i + 1);
    LoadClass(library, toplevel_class, next_class_offset, &klass);
    if (register_class) {
      classes.Add(klass, Heap::kOld);
    }
  }

  if (loading_native_wrappers_library_ || !register_class) {
    FinishTopLevelClassLoading(toplevel_class, library, library_index);
  }

  // Used for mirrors and allows VM to recognize @pragma annotations on
  // libraries.
  if (annotation_count > 0) {
    ASSERT(annotations_kernel_offset > 0);
    library.AddMetadata(library, annotations_kernel_offset);
  }

  if (register_class) {
    helper_.SetOffset(library_index.SourceReferencesOffset());
    intptr_t count = helper_.ReadUInt();
    const GrowableObjectArray& used_scripts =
        GrowableObjectArray::Handle(library.used_scripts());
    Script& script = Script::Handle(Z);
    for (intptr_t i = 0; i < count; i++) {
      intptr_t uri_index = helper_.ReadUInt();
      script = ScriptAt(uri_index);
      used_scripts.Add(script);
    }
  }
  if (!library.Loaded()) library.SetLoaded();

  return library.ptr();
}

void KernelLoader::FinishTopLevelClassLoading(
    const Class& toplevel_class,
    const Library& library,
    const LibraryIndex& library_index) {
  if (toplevel_class.is_loaded()) {
    return;
  }
  TIMELINE_DURATION(Thread::Current(), Isolate, "FinishTopLevelClassLoading");

  ActiveClassScope active_class_scope(&active_class_, &toplevel_class);

  // Offsets within library index are whole program offsets and not
  // relative to the library.
  const intptr_t correction = correction_offset_ - library_kernel_offset_;
  helper_.SetOffset(library_index.ClassOffset(library_index.class_count()) +
                    correction);

  const intptr_t extension_count = helper_.ReadListLength();
  for (intptr_t i = 0; i < extension_count; ++i) {
    helper_.ReadTag();                     // read tag.
    helper_.SkipCanonicalNameReference();  // skip canonical name.
    helper_.SkipStringReference();         // skip name.
    helper_.SkipListOfExpressions();       // skip annotations.
    helper_.ReadUInt();                    // read source uri index.
    helper_.ReadPosition();                // read file offset.
    helper_.ReadByte();                    // skip flags.
    helper_.SkipTypeParametersList();      // skip type parameter list.
    helper_.SkipDartType();                // skip on-type.

    const intptr_t extension_member_count = helper_.ReadListLength();
    for (intptr_t j = 0; j < extension_member_count; ++j) {
      helper_.SkipName();                    // skip name.
      helper_.ReadByte();                    // read kind.
      helper_.ReadByte();                    // read flags.
      helper_.SkipCanonicalNameReference();  // skip member reference
      helper_.SkipCanonicalNameReference();  // skip tear-off reference
    }
  }

  const intptr_t extension_type_declaration_count = helper_.ReadListLength();
  for (intptr_t i = 0; i < extension_type_declaration_count; ++i) {
    helper_.ReadTag();                     // read tag.
    helper_.SkipCanonicalNameReference();  // skip canonical name.
    helper_.SkipStringReference();         // skip name.
    helper_.SkipListOfExpressions();       // skip annotations.
    helper_.ReadUInt();                    // read source uri index.
    helper_.ReadPosition();                // read file offset.
    helper_.ReadByte();                    // skip flags.
    helper_.SkipTypeParametersList();      // skip type parameter list.
    helper_.SkipDartType();                // skip declared representation type.
    helper_.SkipStringReference();         // skip representation name.
    helper_.SkipListOfDartTypes();         // skip implements types.

    // Skip extension type procedures.
    const intptr_t extension_type_procedure_count =
        helper_.ReadListLength();  // read list length.
    for (intptr_t i = 0; i < extension_type_procedure_count; ++i) {
      ProcedureHelper procedure_helper(&helper_);
      procedure_helper.ReadUntilExcluding(ProcedureHelper::kEnd);
    }

    const intptr_t extension_type_member_count = helper_.ReadListLength();
    for (intptr_t j = 0; j < extension_type_member_count; ++j) {
      helper_.SkipName();                    // skip name.
      helper_.ReadByte();                    // read kind.
      helper_.ReadByte();                    // read flags.
      helper_.SkipCanonicalNameReference();  // skip member reference
      helper_.SkipCanonicalNameReference();  // skip tear-off reference
    }
  }

  fields_.Clear();
  functions_.Clear();

  // Load toplevel fields.
  const intptr_t field_count = helper_.ReadListLength();  // read list length.
  for (intptr_t i = 0; i < field_count; ++i) {
    intptr_t field_offset = helper_.ReaderOffset() - correction_offset_;
    ActiveMemberScope active_member_scope(&active_class_, nullptr);
    FieldHelper field_helper(&helper_);
    field_helper.ReadUntilExcluding(FieldHelper::kName);

    const String& name = helper_.ReadNameAsFieldName();
    field_helper.SetJustRead(FieldHelper::kName);

    field_helper.ReadUntilExcluding(FieldHelper::kAnnotations);
    intptr_t annotation_count = helper_.ReadListLength();
    uint32_t pragma_bits = 0;
    ReadVMAnnotations(annotation_count, &pragma_bits);
    field_helper.SetJustRead(FieldHelper::kAnnotations);

    field_helper.ReadUntilExcluding(FieldHelper::kType);
    const Object& script_class =
        ClassForScriptAt(toplevel_class, field_helper.source_uri_index_);
    // In the VM all const fields are implicitly final whereas in Kernel they
    // are not final because they are not explicitly declared that way.
    const bool is_final = field_helper.IsConst() || field_helper.IsFinal();
    // Only instance fields could be covariant.
    ASSERT(!field_helper.IsCovariant() &&
           !field_helper.IsGenericCovariantImpl());
    const bool is_late = field_helper.IsLate();
    const bool is_extension_member = field_helper.IsExtensionMember();
    const bool is_extension_type_member = field_helper.IsExtensionTypeMember();
    const Field& field = Field::Handle(
        Z, Field::NewTopLevel(name, is_final, field_helper.IsConst(), is_late,
                              script_class, field_helper.position_,
                              field_helper.end_position_));
    field.set_kernel_offset(field_offset);
    field.set_has_pragma(HasPragma::decode(pragma_bits));
    field.set_is_extension_member(is_extension_member);
    field.set_is_extension_type_member(is_extension_type_member);
    const AbstractType& type = T.BuildType();  // read type.
    field.SetFieldType(type);
    ReadInferredType(field, field_offset + library_kernel_offset_);
    CheckForInitializer(field);
    // In NNBD libraries, static fields with initializers are
    // implicitly late.
    if (field.has_initializer() && library.is_nnbd()) {
      field.set_is_late(true);
    }
    field_helper.SetJustRead(FieldHelper::kType);
    field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
    intptr_t field_initializer_offset = helper_.ReaderOffset();
    field_helper.ReadUntilExcluding(FieldHelper::kEnd);

    {
      AlternativeReadingScope alt(&helper_.reader_, field_initializer_offset);
      static_field_value_ = ReadInitialFieldValue(field, &field_helper);
    }
    GenerateFieldAccessors(toplevel_class, field, &field_helper);
    IG->RegisterStaticField(field, static_field_value_);

    if ((FLAG_enable_mirrors || HasPragma::decode(pragma_bits)) &&
        annotation_count > 0) {
      library.AddMetadata(field, field_offset);
    }
    fields_.Add(&field);
  }

  ASSERT(!toplevel_class.is_loaded());

  // Load toplevel procedures.
  intptr_t next_procedure_offset =
      library_index.ProcedureOffset(0) + correction;
  const intptr_t procedure_count = library_index.procedure_count();
  for (intptr_t i = 0; i < procedure_count; ++i) {
    helper_.SetOffset(next_procedure_offset);
    next_procedure_offset = library_index.ProcedureOffset(i + 1) + correction;
    LoadProcedure(library, toplevel_class, false, next_procedure_offset);
    // LoadProcedure calls Library::GetMetadata which invokes Dart code
    // which may recursively trigger class finalization and
    // FinishTopLevelClassLoading.
    // In such case, return immediately and avoid overwriting already finalized
    // functions with freshly loaded and not yet finalized.
    if (toplevel_class.is_loaded()) {
      return;
    }
  }

  toplevel_class.SetFields(Array::Handle(MakeFieldsArray()));
  toplevel_class.SetFunctions(Array::Handle(MakeFunctionsArray()));

  String& name = String::Handle(Z);
  for (intptr_t i = 0, n = fields_.length(); i < n; ++i) {
    const Field* field = fields_.At(i);
    name = field->name();
    library.AddObject(*field, name);
  }
  for (intptr_t i = 0, n = functions_.length(); i < n; ++i) {
    const Function* function = functions_.At(i);
    name = function->name();
    library.AddObject(*function, name);
  }

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

void KernelLoader::LoadLibraryImportsAndExports(Library* library,
                                                const Class& toplevel_class) {
  GrowableObjectArray& show_list = GrowableObjectArray::Handle(Z);
  GrowableObjectArray& hide_list = GrowableObjectArray::Handle(Z);
  Array& show_names = Array::Handle(Z);
  Array& hide_names = Array::Handle(Z);
  Namespace& ns = Namespace::Handle(Z);
  LibraryPrefix& library_prefix = LibraryPrefix::Handle(Z);

  const intptr_t deps_count = helper_.ReadListLength();
  const Array& deps = Array::Handle(Array::New(deps_count));
  for (intptr_t dep = 0; dep < deps_count; ++dep) {
    LibraryDependencyHelper dependency_helper(&helper_);

    dependency_helper.ReadUntilExcluding(LibraryDependencyHelper::kAnnotations);
    intptr_t annotations_kernel_offset =
        helper_.ReaderOffset() - correction_offset_;

    dependency_helper.ReadUntilExcluding(LibraryDependencyHelper::kCombinators);

    // Ignore the dependency if the target library is invalid.
    // The error will be caught during compilation.
    if (dependency_helper.target_library_canonical_name_ < 0) {
      const intptr_t combinator_count = helper_.ReadListLength();
      for (intptr_t c = 0; c < combinator_count; ++c) {
        helper_.SkipLibraryCombinator();
      }
      continue;
    }

    // Prepare show and hide lists.
    show_list = GrowableObjectArray::New(Heap::kOld);
    hide_list = GrowableObjectArray::New(Heap::kOld);
    const intptr_t combinator_count = helper_.ReadListLength();
    for (intptr_t c = 0; c < combinator_count; ++c) {
      uint8_t flags = helper_.ReadFlags();
      intptr_t name_count = helper_.ReadListLength();
      for (intptr_t n = 0; n < name_count; ++n) {
        String& show_hide_name =
            H.DartSymbolObfuscate(helper_.ReadStringReference());
        if ((flags & LibraryDependencyHelper::Show) != 0) {
          show_list.Add(show_hide_name, Heap::kOld);
        } else {
          hide_list.Add(show_hide_name, Heap::kOld);
        }
      }
    }

    if (show_list.Length() > 0) {
      show_names = Array::MakeFixedLength(show_list);
    } else {
      show_names = Array::null();
    }

    if (hide_list.Length() > 0) {
      hide_names = Array::MakeFixedLength(hide_list);
    } else {
      hide_names = Array::null();
    }

    Library& target_library = Library::Handle(
        Z, LookupLibrary(dependency_helper.target_library_canonical_name_));
    if (!FLAG_enable_mirrors &&
        target_library.url() == Symbols::DartMirrors().ptr()) {
      H.ReportError(
          "import of dart:mirrors is not supported in the current Dart "
          "runtime");
    }
    if (!Api::IsFfiEnabled() &&
        target_library.url() == Symbols::DartFfi().ptr() &&
        library->url() != Symbols::DartCore().ptr() &&
        library->url() != Symbols::DartInternal().ptr() &&
        library->url() != Symbols::DartFfi().ptr()) {
      H.ReportError(
          "import of dart:ffi is not supported in the current Dart runtime");
    }
    String& prefix = H.DartSymbolPlain(dependency_helper.name_index_);
    ns = Namespace::New(target_library, show_names, hide_names, *library);
    if ((dependency_helper.flags_ & LibraryDependencyHelper::Export) != 0) {
      library->AddExport(ns);
    } else {
      if (prefix.IsNull() || prefix.Length() == 0) {
        library->AddImport(ns);
      } else {
        library_prefix = library->LookupLocalLibraryPrefix(prefix);
        if (!library_prefix.IsNull()) {
          library_prefix.AddImport(ns);
        } else {
          library_prefix = LibraryPrefix::New(
              prefix, ns,
              (dependency_helper.flags_ & LibraryDependencyHelper::Deferred) !=
                  0,
              *library);
          library->AddObject(library_prefix, prefix);
        }
      }
    }

    if (FLAG_enable_mirrors && dependency_helper.annotation_count_ > 0) {
      ASSERT(annotations_kernel_offset > 0);
      library->AddMetadata(ns, annotations_kernel_offset);
    }

    if (prefix.IsNull()) {
      deps.SetAt(dep, ns);
    } else {
      deps.SetAt(dep, library_prefix);
    }
  }

  library->set_dependencies(deps);
}

void KernelLoader::LoadPreliminaryClass(ClassHelper* class_helper,
                                        intptr_t type_parameter_count) {
  const Class* klass = active_class_.klass;

  // Enable access to type_parameters().
  klass->set_is_declaration_loaded();

  // Note: This assumes that ClassHelper is exactly at the position where
  // the length of the type parameters have been read, and that the order in
  // the binary is as follows: [...], kTypeParameters, kSuperClass, kMixinType,
  // kImplementedClasses, [...].

  // Set type parameters.
  T.LoadAndSetupTypeParameters(&active_class_, Object::null_function(), *klass,
                               Object::null_function_type(),
                               type_parameter_count);

  ActiveTypeParametersScope scope(&active_class_, nullptr, Z);

  T.LoadAndSetupBounds(&active_class_, Object::null_function(), *klass,
                       Object::null_function_type(), type_parameter_count);

  // Set super type.  Some classes (e.g., Object) do not have one.
  Tag type_tag = helper_.ReadTag();  // read super class type (part 1).
  if (type_tag == kSomething) {
    AbstractType& super_type =
        T.BuildTypeWithoutFinalization();  // read super class type (part 2).
    klass->set_super_type(Type::Cast(super_type));
  }

  class_helper->SetJustRead(ClassHelper::kSuperClass);
  class_helper->ReadUntilIncluding(ClassHelper::kMixinType);

  // Build implemented interface types
  intptr_t interface_count = helper_.ReadListLength();
  if (interface_count == 0) {
    klass->set_interfaces(Object::empty_array());
  } else {
    const Array& interfaces =
        Array::Handle(Z, Array::New(interface_count, Heap::kOld));
    for (intptr_t i = 0; i < interface_count; i++) {
      const AbstractType& type =
          T.BuildTypeWithoutFinalization();  // read ith type.
      interfaces.SetAt(i, type);
    }
    klass->set_interfaces(interfaces);
  }
  class_helper->SetJustRead(ClassHelper::kImplementedClasses);

  if (class_helper->is_abstract()) {
    klass->set_is_abstract();
  }
  if (class_helper->is_transformed_mixin_application()) {
    klass->set_is_transformed_mixin_application();
  }
  if (class_helper->has_const_constructor()) {
    klass->set_is_const();
  }
  if (class_helper->is_sealed()) {
    klass->set_is_sealed();
  }
  if (class_helper->is_mixin_class()) {
    klass->set_is_mixin_class();
  }
  if (class_helper->is_base()) {
    klass->set_is_base_class();
  }
  if (class_helper->is_interface()) {
    klass->set_is_interface_class();
  }
  if (class_helper->is_final()) {
    klass->set_is_final();
  }
}

void KernelLoader::LoadClass(const Library& library,
                             const Class& toplevel_class,
                             intptr_t class_end,
                             Class* out_class) {
  intptr_t class_offset = helper_.ReaderOffset();
  ClassIndex class_index(program_->binary(), class_offset,
                         class_end - class_offset);

  ClassHelper class_helper(&helper_);
  class_helper.ReadUntilIncluding(ClassHelper::kCanonicalName);
  *out_class = LookupClass(library, class_helper.canonical_name_);
  out_class->set_kernel_offset(class_offset - correction_offset_);

  // The class needs to have a script because all the functions in the class
  // will inherit it.  The predicate Function::IsOptimizable uses the absence of
  // a script to detect test functions that should not be optimized.
  if (out_class->script() == Script::null()) {
    class_helper.ReadUntilIncluding(ClassHelper::kSourceUriIndex);
    const Script& script =
        Script::Handle(Z, ScriptAt(class_helper.source_uri_index_));
    out_class->set_script(script);
  }
  if (out_class->token_pos() == TokenPosition::kNoSource) {
    class_helper.ReadUntilIncluding(ClassHelper::kEndPosition);
    out_class->set_token_pos(class_helper.start_position_);
    out_class->set_end_token_pos(class_helper.end_position_);
  }

  class_helper.ReadUntilIncluding(ClassHelper::kFlags);
  if (class_helper.is_enum_class()) {
    out_class->set_is_enum_class();
  }

  class_helper.ReadUntilExcluding(ClassHelper::kAnnotations);
  intptr_t annotation_count = helper_.ReadListLength();
  uint32_t pragma_bits = 0;
  ReadVMAnnotations(annotation_count, &pragma_bits);
  if (IsolateUnsendablePragma::decode(pragma_bits)) {
    out_class->set_is_isolate_unsendable_due_to_pragma(true);
  }
  if (DeeplyImmutablePragma::decode(pragma_bits)) {
    out_class->set_is_deeply_immutable(true);
    // Ensure that the pragma implies deeply immutability for VM recognized
    // classes.
    ASSERT(out_class->id() >= kNumPredefinedCids ||
           IsDeeplyImmutableCid(out_class->id()));
  }
  if (HasPragma::decode(pragma_bits)) {
    out_class->set_has_pragma(true);
  }
  class_helper.SetJustRead(ClassHelper::kAnnotations);
  class_helper.ReadUntilExcluding(ClassHelper::kTypeParameters);
  intptr_t type_parameter_counts =
      helper_.ReadListLength();  // read type_parameters list length.

  ActiveClassScope active_class_scope(&active_class_, out_class);
  if (!out_class->is_declaration_loaded()) {
    LoadPreliminaryClass(&class_helper, type_parameter_counts);
  } else {
    ASSERT(type_parameter_counts == 0);
    class_helper.SetJustRead(ClassHelper::kTypeParameters);
  }

  if ((FLAG_enable_mirrors || HasPragma::decode(pragma_bits)) &&
      annotation_count > 0) {
    library.AddMetadata(*out_class, class_offset - correction_offset_);
  }

  // We do not register expression evaluation classes 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.
  const bool register_class =
      library.ptr() != expression_evaluation_library_.ptr();
  if (!register_class) {
    H.SetExpressionEvaluationClass(*out_class);
  }

  if (loading_native_wrappers_library_ || !register_class) {
    FinishClassLoading(*out_class, library, toplevel_class, class_offset,
                       class_index, &class_helper);
  }

  helper_.SetOffset(class_end);
}

void KernelLoader::FinishClassLoading(const Class& klass,
                                      const Library& library,
                                      const Class& toplevel_class,
                                      intptr_t class_offset,
                                      const ClassIndex& class_index,
                                      ClassHelper* class_helper) {
  if (klass.is_loaded()) {
    return;
  }

  TIMELINE_DURATION(Thread::Current(), Isolate, "FinishClassLoading");

  ActiveClassScope active_class_scope(&active_class_, &klass);

  // 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 = klass.InjectCIDFields();

  fields_.Clear();
  functions_.Clear();
  if (!discard_fields) {
    class_helper->ReadUntilExcluding(ClassHelper::kFields);
    int field_count = helper_.ReadListLength();  // read list length.
    for (intptr_t i = 0; i < field_count; ++i) {
      intptr_t field_offset = helper_.ReaderOffset() - correction_offset_;
      ActiveMemberScope active_member(&active_class_, nullptr);
      FieldHelper field_helper(&helper_);

      field_helper.ReadUntilIncluding(FieldHelper::kSourceUriIndex);
      const Object& script_class =
          ClassForScriptAt(klass, field_helper.source_uri_index_);

      field_helper.ReadUntilExcluding(FieldHelper::kName);
      const String& name = helper_.ReadNameAsFieldName();
      field_helper.SetJustRead(FieldHelper::kName);

      field_helper.ReadUntilExcluding(FieldHelper::kAnnotations);
      const intptr_t annotation_count = helper_.ReadListLength();
      uint32_t pragma_bits = 0;
      ReadVMAnnotations(annotation_count, &pragma_bits);
      field_helper.SetJustRead(FieldHelper::kAnnotations);

      field_helper.ReadUntilExcluding(FieldHelper::kType);
      const AbstractType& type =
          T.BuildTypeWithoutFinalization();  // read type.
      field_helper.SetJustRead(FieldHelper::kType);

      const bool is_reflectable =
          field_helper.position_.IsReal() &&
          !(library.is_dart_scheme() && library.IsPrivate(name));
      // In the VM all const fields are implicitly final whereas in Kernel they
      // are not final because they are not explicitly declared that way.
      const bool is_final = field_helper.IsConst() || field_helper.IsFinal();
      const bool is_late = field_helper.IsLate();
      const bool is_extension_member = field_helper.IsExtensionMember();
      const bool is_extension_type_member =
          field_helper.IsExtensionTypeMember();
      Field& field = Field::Handle(
          Z, Field::New(name, field_helper.IsStatic(), is_final,
                        field_helper.IsConst(), is_reflectable, is_late,
                        script_class, type, field_helper.position_,
                        field_helper.end_position_));
      field.set_kernel_offset(field_offset);
      field.set_has_pragma(HasPragma::decode(pragma_bits));
      field.set_is_covariant(field_helper.IsCovariant());
      field.set_is_generic_covariant_impl(
          field_helper.IsGenericCovariantImpl());
      field.set_is_extension_member(is_extension_member);
      field.set_is_extension_type_member(is_extension_type_member);
      ReadInferredType(field, field_offset + library_kernel_offset_);
      CheckForInitializer(field);
      // In NNBD libraries, static fields with initializers are
      // implicitly late.
      if (field_helper.IsStatic() && field.has_initializer() &&
          library.is_nnbd()) {
        field.set_is_late(true);
      }
      field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
      intptr_t field_initializer_offset = helper_.ReaderOffset();
      field_helper.ReadUntilExcluding(FieldHelper::kEnd);

      {
        AlternativeReadingScope alt(&helper_.reader_, field_initializer_offset);
        static_field_value_ = ReadInitialFieldValue(field, &field_helper);
      }
      GenerateFieldAccessors(klass, field, &field_helper);
      if (field.is_static()) {
        IG->RegisterStaticField(field, static_field_value_);
      }
      if ((FLAG_enable_mirrors || HasPragma::decode(pragma_bits)) &&
          annotation_count > 0) {
        library.AddMetadata(field, field_offset);
      }
      fields_.Add(&field);
    }
    class_helper->SetJustRead(ClassHelper::kFields);

    if (klass.is_enum_class()) {
      // Add static field 'const _deleted_enum_sentinel'.
      // This field does not need to be of type E.
      Field& deleted_enum_sentinel = Field::ZoneHandle(Z);
      deleted_enum_sentinel =
          Field::New(Symbols::_DeletedEnumSentinel(),
                     /* is_static = */ true,
                     /* is_final = */ true,
                     /* is_const = */ true,
                     /* is_reflectable = */ false,
                     /* is_late = */ false, klass, Object::dynamic_type(),
                     TokenPosition::kNoSource, TokenPosition::kNoSource);
      IG->RegisterStaticField(deleted_enum_sentinel, Object::Handle());
      fields_.Add(&deleted_enum_sentinel);
    }

    // TODO(https://dartbug.com/44454): Make VM recognize the Struct class.
    //
    // The FfiTrampolines currently allocate subtypes of structs and store
    // TypedData in them, without using guards because they are force
    // optimized. We immediately set the guarded_cid_ to kDynamicCid, which
    // is effectively the same as calling this method first with Pointer and
    // subsequently with TypedData with field guards.
    if (klass.UserVisibleName() == Symbols::Compound().ptr() &&
        Library::Handle(Z, klass.library()).url() == Symbols::DartFfi().ptr()) {
      ASSERT_EQUAL(fields_.length(), 2);
      ASSERT(String::Handle(Z, fields_[0]->name())
                 .StartsWith(Symbols::_typedDataBase()));
      fields_[0]->set_guarded_cid(kDynamicCid);
      fields_[0]->set_is_nullable(true);
    }

    // Check that subclasses of AbiSpecificInteger have a mapping for the
    // current ABI.
    //
    // TODO(https://github.com/dart-lang/language/issues/1889): If we make
    // kernel know about the target platform, we can move this check to the
    // frontend.
    const auto& super_class = Class::Handle(Z, klass.SuperClass());
    if (!super_class.IsNull() &&
        super_class.UserVisibleName() == Symbols::AbiSpecificInteger().ptr() &&
        Library::Handle(Z, super_class.library()).url() ==
            Symbols::DartFfi().ptr()) {
      const char* error = nullptr;
      compiler::ffi::NativeType::FromAbstractType(
          Z, AbstractType::Handle(Z, klass.DeclarationType()), &error);
      if (error != nullptr) {
        H.ReportError("%s", error);
      }
    }

    // Due to ReadVMAnnotations(), the klass may have been loaded at this point
    // (loading the class while evaluating annotations).
    if (klass.is_loaded()) {
      return;
    }

    klass.SetFields(Array::Handle(Z, MakeFieldsArray()));
  }

  class_helper->ReadUntilExcluding(ClassHelper::kConstructors);
  int constructor_count = helper_.ReadListLength();  // read list length.
  for (intptr_t i = 0; i < constructor_count; ++i) {
    intptr_t constructor_offset = helper_.ReaderOffset() - correction_offset_;
    ActiveMemberScope active_member_scope(&active_class_, nullptr);
    ConstructorHelper constructor_helper(&helper_);
    constructor_helper.ReadUntilExcluding(ConstructorHelper::kAnnotations);
    const intptr_t annotation_count = helper_.ReadListLength();
    uint32_t pragma_bits = 0;
    ReadVMAnnotations(annotation_count, &pragma_bits);
    constructor_helper.SetJustRead(ConstructorHelper::kAnnotations);
    constructor_helper.ReadUntilExcluding(ConstructorHelper::kFunction);

    const String& name =
        H.DartConstructorName(constructor_helper.canonical_name_);

    // We can have synthetic constructors, which will not have a source uri
    // attached to them (which means the index into the source uri table is 0,
    // see `package:kernel/binary/ast_to_binary::writeUriReference`.
    const Object* owner = &klass;
    const intptr_t source_uri_index = constructor_helper.source_uri_index_;
    if (source_uri_index != 0) {
      owner = &ClassForScriptAt(klass, source_uri_index);
    }

    FunctionType& signature = FunctionType::Handle(Z, FunctionType::New());
    const Function& function = Function::ZoneHandle(
        Z, Function::New(signature, name, UntaggedFunction::kConstructor,
                         false,  // is_static
                         constructor_helper.IsConst(),
                         false,  // is_abstract
                         constructor_helper.IsExternal(),
                         false,  // is_native
                         *owner, constructor_helper.start_position_));
    function.set_end_token_pos(constructor_helper.end_position_);
    function.set_kernel_offset(constructor_offset);
    signature.set_result_type(T.ReceiverType(klass));
    function.set_has_pragma(HasPragma::decode(pragma_bits));
    function.set_is_visible(!InvisibleFunctionPragma::decode(pragma_bits));

    FunctionNodeHelper function_node_helper(&helper_);
    function_node_helper.ReadUntilExcluding(
        FunctionNodeHelper::kTypeParameters);
    T.SetupFunctionParameters(klass, function,
                              true,   // is_method
                              false,  // is_closure
                              &function_node_helper);
    T.SetupUnboxingInfoMetadata(function, library_kernel_offset_);

    if (library.is_dart_scheme() &&
        H.IsPrivate(constructor_helper.canonical_name_)) {
      function.set_is_reflectable(false);
    }

    if (constructor_helper.IsSynthetic()) {
      function.set_is_debuggable(false);
    }

    function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
    constructor_helper.SetJustRead(ConstructorHelper::kFunction);
    constructor_helper.ReadUntilExcluding(ConstructorHelper::kEnd);

    if (klass.is_finalized()) {
      // The owner class has already been marked as finalized (e.g. class
      // 'NativeFieldWrapperClass1'), so the signature of this added constructor
      // must be finalized here, since finalization of member types will not be
      // called anymore.
      signature ^= ClassFinalizer::FinalizeType(signature);
      function.SetSignature(signature);
    }
    functions_.Add(&function);

    if ((FLAG_enable_mirrors || HasPragma::decode(pragma_bits)) &&
        annotation_count > 0) {
      library.AddMetadata(function, constructor_offset);
    }
  }

  // Due to ReadVMAnnotations(), the klass may have been loaded at this point
  // (loading the class while evaluating annotations).
  if (klass.is_loaded()) {
    return;
  }

  // Everything up til the procedures are skipped implicitly, and class_helper
  // is no longer used.

  intptr_t procedure_count = class_index.procedure_count();
  // Procedure offsets within a class index are whole program offsets and not
  // relative to the library of the class. Hence, we need a correction to get
  // the currect procedure offset within the current data.
  intptr_t correction = correction_offset_ - library_kernel_offset_;
  intptr_t next_procedure_offset = class_index.ProcedureOffset(0) + correction;
  for (intptr_t i = 0; i < procedure_count; ++i) {
    helper_.SetOffset(next_procedure_offset);
    next_procedure_offset = class_index.ProcedureOffset(i + 1) + correction;
    LoadProcedure(library, klass, true, next_procedure_offset);
    // LoadProcedure calls Library::GetMetadata which invokes Dart code
    // which may recursively trigger class finalization and FinishClassLoading.
    // In such case, return immediately and avoid overwriting already finalized
    // functions with freshly loaded and not yet finalized.
    if (klass.is_loaded()) {
      return;
    }
  }

  klass.SetFunctions(Array::Handle(MakeFunctionsArray()));

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

void KernelLoader::FinishLoading(const Class& klass) {
  ASSERT(klass.IsTopLevel() || (klass.kernel_offset() > 0));

  Zone* zone = Thread::Current()->zone();
  const Library& library = Library::Handle(zone, klass.library());
  const Class& toplevel_class = Class::Handle(zone, library.toplevel_class());
  const auto& library_kernel_data =
      TypedDataView::Handle(zone, library.KernelLibrary());
  ASSERT(!library_kernel_data.IsNull());

  const auto& kernel_info =
      KernelProgramInfo::Handle(zone, klass.KernelProgramInfo());
  const intptr_t library_kernel_offset =
      kernel_info.KernelLibraryStartOffset(library.kernel_library_index());

  KernelLoader kernel_loader(kernel_info, library_kernel_data,
                             library_kernel_offset);

  LibraryIndex library_index(library_kernel_data);

  if (klass.IsTopLevel()) {
    ASSERT(klass.ptr() == toplevel_class.ptr());
    kernel_loader.FinishTopLevelClassLoading(klass, library, library_index);
    return;
  }

  const intptr_t class_offset = klass.kernel_offset();
  ClassIndex class_index(
      library_kernel_data, class_offset,
      // Class offsets in library index are whole program offsets.
      // Hence, we need to add |library_kernel_offset| to
      // |class_offset| to lookup the entry for the class in the library
      // index.
      library_index.SizeOfClassAtOffset(class_offset + library_kernel_offset));

  kernel_loader.helper_.SetOffset(class_offset);
  ClassHelper class_helper(&kernel_loader.helper_);

  kernel_loader.FinishClassLoading(klass, library, toplevel_class, class_offset,
                                   class_index, &class_helper);
}

// Read annotations on a procedure or a class to identify potential VM-specific
// directives.
//
// Output parameters:
//
//   `native_name`: the native name if @pragma('vm:external-name)` was found.
//
//   `pragma_bits`: any recognized pragma that was found
//
void KernelLoader::ReadVMAnnotations(intptr_t annotation_count,
                                     uint32_t* pragma_bits,
                                     String* native_name) {
  *pragma_bits = 0;
  if (annotation_count == 0) {
    return;
  }

  for (intptr_t i = 0; i < annotation_count; ++i) {
    const intptr_t tag = helper_.PeekTag();
    if (tag == kConstantExpression || tag == kFileUriConstantExpression) {
      helper_.ReadByte();      // Skip the tag.
      helper_.ReadPosition();  // Skip fileOffset.
      if (tag == kFileUriConstantExpression) {
        helper_.ReadUInt();  // Skip uri.
      }
      helper_.SkipDartType();  // Skip type.
      const intptr_t index_in_constant_table = helper_.ReadUInt();

      // Prepare lazy constant reading.
      ConstantReader constant_reader(&helper_, &active_class_);

      intptr_t name_index = -1;
      intptr_t options_index = -1;
      if (constant_reader.IsPragmaInstanceConstant(
              index_in_constant_table, &name_index, &options_index)) {
        *pragma_bits = HasPragma::update(true, *pragma_bits);

        if (constant_reader.IsStringConstant(name_index, "vm:invisible")) {
          *pragma_bits = InvisibleFunctionPragma::update(true, *pragma_bits);
        }
        if (constant_reader.IsStringConstant(name_index, "vm:external-name")) {
          *pragma_bits = ExternalNamePragma::update(true, *pragma_bits);
          constant_reader.GetStringConstant(options_index, native_name);
        }
        if (constant_reader.IsStringConstant(name_index,
                                             "vm:isolate-unsendable")) {
          *pragma_bits = IsolateUnsendablePragma::update(true, *pragma_bits);
        }
        if (constant_reader.IsStringConstant(name_index,
                                             "vm:deeply-immutable")) {
          *pragma_bits = DeeplyImmutablePragma::update(true, *pragma_bits);
        }
        if (constant_reader.IsStringConstant(name_index, "vm:ffi:native")) {
          *pragma_bits = FfiNativePragma::update(true, *pragma_bits);
        }
      }
    } else {
      helper_.SkipExpression();
      continue;
    }
  }
}

void KernelLoader::LoadProcedure(const Library& library,
                                 const Class& owner,
                                 bool in_class,
                                 intptr_t procedure_end) {
  intptr_t procedure_offset = helper_.ReaderOffset() - correction_offset_;
  ProcedureHelper procedure_helper(&helper_);

  procedure_helper.ReadUntilExcluding(ProcedureHelper::kAnnotations);
  // CFE adds 'member signature' abstract functions to a legacy class deriving
  // or implementing an opted-in interface. The signature of these functions is
  // legacy erased and used as the target of interface calls. They are used for
  // static reasoning about the program by CFE, but not really needed by the VM.
  // In certain situations (e.g. issue 162073826), a large number of these
  // additional functions can cause strain on the VM. They are therefore skipped
  // in jit mode and their associated origin function is used instead as
  // interface call target.
  if (!FLAG_precompiled_mode && procedure_helper.IsMemberSignature()) {
    helper_.SetOffset(procedure_end);
    return;
  }
  const String& name = H.DartProcedureName(procedure_helper.canonical_name_);
  bool is_method = in_class && !procedure_helper.IsStatic();
  bool is_abstract = procedure_helper.IsAbstract();
  bool is_external = procedure_helper.IsExternal();
  bool is_extension_member = procedure_helper.IsExtensionMember();
  bool is_extension_type_member = procedure_helper.IsExtensionTypeMember();
  bool is_synthetic = procedure_helper.IsSynthetic();
  String& native_name = String::Handle(Z);
  uint32_t pragma_bits = 0;
  const intptr_t annotation_count = helper_.ReadListLength();
  ReadVMAnnotations(annotation_count, &pragma_bits, &native_name);
  is_external = is_external && native_name.IsNull();
  procedure_helper.SetJustRead(ProcedureHelper::kAnnotations);
  const Object& script_class =
      ClassForScriptAt(owner, procedure_helper.source_uri_index_);
  UntaggedFunction::Kind kind = GetFunctionType(procedure_helper.kind_);

  // We do not register expression evaluation libraries 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.
  const bool register_function = !name.Equals(Symbols::DebugProcedureName());

  const bool is_ffi_native = FfiNativePragma::decode(pragma_bits);
  const FunctionType& signature = FunctionType::Handle(Z, FunctionType::New());
  const Function& function = Function::ZoneHandle(
      Z, Function::New(signature, name, kind,
                       !is_method,  // is_static
                       false,       // is_const
                       is_abstract, is_external,
                       !native_name.IsNull() || is_ffi_native,  // is_native
                       script_class, procedure_helper.start_position_));
  function.set_has_pragma(HasPragma::decode(pragma_bits));
  function.set_end_token_pos(procedure_helper.end_position_);
  function.set_is_synthetic(procedure_helper.IsNoSuchMethodForwarder() ||
                            procedure_helper.IsMemberSignature() ||
                            is_synthetic);
  function.set_is_visible(!InvisibleFunctionPragma::decode(pragma_bits));
  if (register_function) {
    functions_.Add(&function);
  } else {
    H.SetExpressionEvaluationFunction(function);
  }
  function.set_kernel_offset(procedure_offset);
  function.set_is_extension_member(is_extension_member);
  function.set_is_extension_type_member(is_extension_type_member);
  if ((library.is_dart_scheme() &&
       H.IsPrivate(procedure_helper.canonical_name_)) ||
      (function.is_static() && (library.ptr() == Library::InternalLibrary()))) {
    function.set_is_reflectable(false);
  }
  if (procedure_helper.IsMemberSignature()) {
    function.set_is_reflectable(false);
  }

  ActiveMemberScope active_member(&active_class_, &function);

  procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction);

  FunctionNodeHelper function_node_helper(&helper_);
  function_node_helper.ReadUntilIncluding(FunctionNodeHelper::kDartAsyncMarker);
  if (function_node_helper.async_marker_ == FunctionNodeHelper::kAsync) {
    function.set_modifier(UntaggedFunction::kAsync);
    function.set_is_inlinable(false);
    ASSERT(function.IsAsyncFunction());
  } else if (function_node_helper.async_marker_ ==
             FunctionNodeHelper::kAsyncStar) {
    function.set_modifier(UntaggedFunction::kAsyncGen);
    function.set_is_inlinable(false);
    ASSERT(function.IsAsyncGenerator());
  } else if (function_node_helper.async_marker_ ==
             FunctionNodeHelper::kSyncStar) {
    function.set_modifier(UntaggedFunction::kSyncGen);
    function.set_is_inlinable(false);
    ASSERT(function.IsSyncGenerator());
  } else {
    ASSERT(function_node_helper.async_marker_ == FunctionNodeHelper::kSync);
    ASSERT(!function.IsAsyncFunction());
    ASSERT(!function.IsAsyncGenerator());
    ASSERT(!function.IsSyncGenerator());
  }

  if (!native_name.IsNull()) {
    function.set_native_name(native_name);
  }

  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
  T.SetupFunctionParameters(owner, function, is_method,
                            false,  // is_closure
                            &function_node_helper);
  T.SetupUnboxingInfoMetadata(function, library_kernel_offset_);

  function_node_helper.ReadUntilExcluding(
      FunctionNodeHelper::kRedirectingFactoryTarget);
  function.set_is_redirecting_factory(helper_.ReadTag() == kSomething);

  // Everything else is skipped implicitly, and procedure_helper and
  // function_node_helper are no longer used.
  helper_.SetOffset(procedure_end);

  if (annotation_count > 0) {
    library.AddMetadata(function, procedure_offset);
  }
}

const Object& KernelLoader::ClassForScriptAt(const Class& klass,
                                             intptr_t source_uri_index) {
  const Script& correct_script = Script::Handle(Z, ScriptAt(source_uri_index));
  if (klass.script() != correct_script.ptr()) {
    // Lazily create the [patch_classes_] array in case we need it.
    if (patch_classes_.IsNull()) {
      const Array& scripts = Array::Handle(Z, kernel_program_info_.scripts());
      ASSERT(!scripts.IsNull());
      patch_classes_ = Array::New(scripts.Length(), Heap::kOld);
    }

    // Use cache for patch classes. This works best for in-order usages.
    PatchClass& patch_class = PatchClass::Handle(Z);
    patch_class ^= patch_classes_.At(source_uri_index);
    if (patch_class.IsNull() || patch_class.wrapped_class() != klass.ptr()) {
      const auto& lib = Library::Handle(klass.library());
      patch_class =
          PatchClass::New(klass, kernel_program_info_, correct_script);
      patch_class.set_kernel_library_index(lib.kernel_library_index());
      patch_classes_.SetAt(source_uri_index, patch_class);
    }
    return patch_class;
  }
  return klass;
}

ScriptPtr KernelLoader::LoadScriptAt(intptr_t index,
                                     UriToSourceTable* uri_to_source_table) {
  const String& uri_string = helper_.SourceTableUriFor(index);
  const String& import_uri_string = helper_.SourceTableImportUriFor(index);
  auto& constant_coverage = TypedDataView::Handle(Z);
  NOT_IN_PRODUCT(constant_coverage = helper_.GetConstantCoverageFor(index));

  String& sources = String::Handle(Z);
  TypedData& line_starts = TypedData::Handle(Z);

  if (uri_to_source_table != nullptr) {
    UriToSourceTableEntry wrapper;
    wrapper.uri = &uri_string;
    UriToSourceTableEntry* pair = uri_to_source_table->LookupValue(&wrapper);
    if (pair != nullptr) {
      sources = pair->sources->ptr();
      line_starts = pair->line_starts->ptr();
    }
  }

  if (sources.IsNull() || line_starts.IsNull()) {
    const String& script_source = helper_.GetSourceFor(index);
    line_starts = helper_.GetLineStartsFor(index);

    if (script_source.ptr() == Symbols::Empty().ptr() &&
        line_starts.Length() == 0 && uri_string.Length() > 0) {
      // Entry included only to provide URI - actual source should already exist
      // in the VM, so try to find it.
      Library& lib = Library::Handle(Z);
      Script& script = Script::Handle(Z);
      const GrowableObjectArray& libs =
          GrowableObjectArray::Handle(IG->object_store()->libraries());
      for (intptr_t i = 0; i < libs.Length(); i++) {
        lib ^= libs.At(i);
        script = lib.LookupScript(uri_string, /* useResolvedUri = */ true);
        if (!script.IsNull()) {
          sources = script.Source();
          line_starts = script.line_starts();
          break;
        }
      }
    } else {
      sources = script_source.ptr();
    }
  }

  const Script& script =
      Script::Handle(Z, Script::New(import_uri_string, uri_string, sources));
  script.InitializeFromKernel(kernel_program_info_, index, line_starts,
                              constant_coverage);
  return script.ptr();
}

ObjectPtr KernelLoader::ReadInitialFieldValue(const Field& field,
                                              FieldHelper* field_helper) {
  const Tag tag = helper_.PeekTag();
  const bool has_initializer = (tag == kSomething);

  if (has_initializer) {
    SimpleExpressionConverter converter(&H, &helper_);
    const bool has_simple_initializer =
        converter.IsSimple(helper_.ReaderOffset() + 1);  // ignore the tag.
    if (has_simple_initializer) {
      if (field_helper->IsStatic()) {
        return converter.SimpleValue().ptr();
      } else {
        field.RecordStore(converter.SimpleValue());
      }
    }
  }

  if (field_helper->IsStatic()) {
    if (!has_initializer && !field_helper->IsLate()) {
      // Static fields without an initializer are implicitly initialized to
      // null.
      return Instance::null();
    }
  }
  ASSERT(field.NeedsGetter());

  // If static, we do need a getter that evaluates the initializer if necessary.
  return field_helper->IsStatic() ? Object::sentinel().ptr() : Object::null();
}

void KernelLoader::GenerateFieldAccessors(const Class& klass,
                                          const Field& field,
                                          FieldHelper* field_helper) {
  const bool needs_getter = field.NeedsGetter();
  const bool needs_setter = field.NeedsSetter();

  if (!needs_getter && !needs_setter) {
    return;
  }

  const Object& script_class =
      ClassForScriptAt(klass, field_helper->source_uri_index_);
  const AbstractType& field_type = AbstractType::Handle(Z, field.type());

  if (needs_getter) {
    const String& getter_name =
        H.DartGetterName(field_helper->canonical_name_getter_);
    const FunctionType& signature =
        FunctionType::Handle(Z, FunctionType::New());
    Function& getter = Function::ZoneHandle(
        Z,
        Function::New(
            signature, getter_name,
            field_helper->IsStatic() ? UntaggedFunction::kImplicitStaticGetter
                                     : UntaggedFunction::kImplicitGetter,
            field_helper->IsStatic(),
            // The functions created by the parser have is_const for static
            // fields that are const (not just final) and they have is_const
            // for non-static fields that are final.
            field_helper->IsStatic() ? field_helper->IsConst()
                                     : field_helper->IsFinal(),
            false,  // is_abstract
            false,  // is_external
            false,  // is_native
            script_class, field_helper->position_));
    functions_.Add(&getter);
    getter.set_end_token_pos(field_helper->end_position_);
    getter.set_kernel_offset(field.kernel_offset());
    signature.set_result_type(field_type);
    getter.set_is_debuggable(false);
    getter.set_accessor_field(field);
    getter.set_is_extension_member(field.is_extension_member());
    getter.set_is_extension_type_member(field.is_extension_type_member());
    H.SetupFieldAccessorFunction(klass, getter, field_type);
    T.SetupUnboxingInfoMetadataForFieldAccessors(getter,
                                                 library_kernel_offset_);
  }

  if (needs_setter) {
    // Only static fields can be const.
    ASSERT(!field_helper->IsConst());
    const String& setter_name =
        H.DartSetterName(field_helper->canonical_name_setter_);
    const FunctionType& signature =
        FunctionType::Handle(Z, FunctionType::New());
    Function& setter = Function::ZoneHandle(
        Z,
        Function::New(signature, setter_name, UntaggedFunction::kImplicitSetter,
                      field_helper->IsStatic(),
                      false,  // is_const
                      false,  // is_abstract
                      false,  // is_external
                      false,  // is_native
                      script_class, field_helper->position_));
    functions_.Add(&setter);
    setter.set_end_token_pos(field_helper->end_position_);
    setter.set_kernel_offset(field.kernel_offset());
    signature.set_result_type(Object::void_type());
    setter.set_is_debuggable(false);
    setter.set_accessor_field(field);
    setter.set_is_extension_member(field.is_extension_member());
    setter.set_is_extension_type_member(field.is_extension_type_member());
    H.SetupFieldAccessorFunction(klass, setter, field_type);
    T.SetupUnboxingInfoMetadataForFieldAccessors(setter,
                                                 library_kernel_offset_);
  }
}

LibraryPtr KernelLoader::LookupLibraryOrNull(NameIndex library) {
  LibraryPtr result;
  name_index_handle_ = Smi::New(library);
  {
    result = kernel_program_info_.LookupLibrary(thread_, name_index_handle_);
    NoSafepointScope no_safepoint_scope(thread_);
    if (result != Library::null()) {
      return result;
    }
  }
  const String& url = H.DartString(H.CanonicalNameString(library));
  {
    result = Library::LookupLibrary(thread_, url);
    NoSafepointScope no_safepoint_scope(thread_);
    if (result == Library::null()) {
      return result;
    }
  }
  const Library& handle = Library::Handle(Z, result);
  name_index_handle_ = Smi::New(library);
  return kernel_program_info_.InsertLibrary(thread_, name_index_handle_,
                                            handle);
}

LibraryPtr KernelLoader::LookupLibrary(NameIndex library) {
  name_index_handle_ = Smi::New(library);
  {
    LibraryPtr result =
        kernel_program_info_.LookupLibrary(thread_, name_index_handle_);
    NoSafepointScope no_safepoint_scope(thread_);
    if (result != Library::null()) {
      return result;
    }
  }

  Library& handle = Library::Handle(Z);
  const String& url = H.DartSymbolPlain(H.CanonicalNameString(library));
  // We do not register expression evaluation libraries 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 (url.Equals(Symbols::EvalSourceUri())) {
    if (expression_evaluation_library_.IsNull()) {
      handle = Library::New(url);
      expression_evaluation_library_ = handle.ptr();
    }
    return expression_evaluation_library_.ptr();
  }
  handle = Library::LookupLibrary(thread_, url);
  if (handle.IsNull()) {
    handle = Library::New(url);
    handle.Register(thread_);
  }
  ASSERT(!handle.IsNull());
  name_index_handle_ = Smi::New(library);
  return kernel_program_info_.InsertLibrary(thread_, name_index_handle_,
                                            handle);
}

LibraryPtr KernelLoader::LookupLibraryFromClass(NameIndex klass) {
  return LookupLibrary(H.CanonicalNameParent(klass));
}

ClassPtr KernelLoader::LookupClass(const Library& library, NameIndex klass) {
  name_index_handle_ = Smi::New(klass);
  {
    ClassPtr raw_class =
        kernel_program_info_.LookupClass(thread_, name_index_handle_);
    NoSafepointScope no_safepoint_scope(thread_);
    if (raw_class != Class::null()) {
      return raw_class;
    }
  }

  ASSERT(!library.IsNull());
  const String& name = H.DartClassName(klass);
  Class& handle = Class::Handle(Z, library.LookupClass(name));
  bool register_class = true;
  if (handle.IsNull()) {
    // We do not register expression evaluation classes 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.
    register_class = library.ptr() != expression_evaluation_library_.ptr();

    handle = Class::New(library, name, Script::Handle(Z),
                        TokenPosition::kNoSource, register_class);
    if (register_class) {
      library.AddClass(handle);
    }
  }
  ASSERT(!handle.IsNull());
  if (register_class) {
    name_index_handle_ = Smi::New(klass);
    kernel_program_info_.InsertClass(thread_, name_index_handle_, handle);
  }
  return handle.ptr();
}

UntaggedFunction::Kind KernelLoader::GetFunctionType(
    ProcedureHelper::Kind procedure_kind) {
  intptr_t lookuptable[] = {
      UntaggedFunction::kRegularFunction,  // Procedure::kMethod
      UntaggedFunction::kGetterFunction,   // Procedure::kGetter
      UntaggedFunction::kSetterFunction,   // Procedure::kSetter
      UntaggedFunction::kRegularFunction,  // Procedure::kOperator
      UntaggedFunction::kConstructor,      // Procedure::kFactory
  };
  intptr_t kind = static_cast<int>(procedure_kind);
  ASSERT(0 <= kind && kind <= ProcedureHelper::kFactory);
  return static_cast<UntaggedFunction::Kind>(lookuptable[kind]);
}

FunctionPtr KernelLoader::LoadClosureFunction(const Function& parent_function,
                                              const Object& closure_owner) {
  const intptr_t func_decl_offset = helper_.ReaderOffset();
  const Tag tag = helper_.ReadTag();
  ASSERT((tag == kFunctionExpression) || (tag == kFunctionDeclaration));
  const bool is_declaration = (tag == kFunctionDeclaration);

  TokenPosition position = helper_.ReadPosition();  // read position.

  uint32_t pragma_bits = 0;
  intptr_t annotation_count = 0;
  const String* name;
  if (is_declaration) {
    // Read variable declaration.
    VariableDeclarationHelper variable_helper(&helper_);

    variable_helper.ReadUntilExcluding(VariableDeclarationHelper::kAnnotations);
    const intptr_t annotation_count = helper_.ReadListLength();
    ReadVMAnnotations(annotation_count, &pragma_bits);
    variable_helper.SetJustRead(VariableDeclarationHelper::kAnnotations);

    variable_helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);
    name = &H.DartSymbolObfuscate(variable_helper.name_index_);
  } else {
    name = &Symbols::AnonymousClosure();
  }

  const intptr_t func_node_offset = helper_.ReaderOffset();

  FunctionNodeHelper function_node_helper(&helper_);
  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);

  Function& function = Function::Handle(Z);
  if (!closure_owner.IsNull()) {
    function = Function::NewClosureFunctionWithKind(
        UntaggedFunction::kClosureFunction, *name, parent_function,
        parent_function.is_static(), position, closure_owner);
  } else {
    function = Function::NewClosureFunction(*name, parent_function, position);
  }

  const bool has_pragma = HasPragma::decode(pragma_bits);
  function.set_has_pragma(has_pragma);
  function.set_is_visible(!InvisibleFunctionPragma::decode(pragma_bits));
  if ((FLAG_enable_mirrors && (annotation_count > 0)) || has_pragma) {
    const auto& lib =
        Library::Handle(Z, Class::Handle(Z, function.Owner()).library());
    lib.AddMetadata(function, func_decl_offset);
  }

  if (function_node_helper.async_marker_ == FunctionNodeHelper::kAsync) {
    function.set_modifier(UntaggedFunction::kAsync);
    function.set_is_inlinable(false);
    ASSERT(function.IsAsyncFunction());
  } else if (function_node_helper.async_marker_ ==
             FunctionNodeHelper::kAsyncStar) {
    function.set_modifier(UntaggedFunction::kAsyncGen);
    function.set_is_inlinable(false);
    ASSERT(function.IsAsyncGenerator());
  } else if (function_node_helper.async_marker_ ==
             FunctionNodeHelper::kSyncStar) {
    function.set_modifier(UntaggedFunction::kSyncGen);
    function.set_is_inlinable(false);
    ASSERT(function.IsSyncGenerator());
  } else {
    ASSERT(function_node_helper.async_marker_ == FunctionNodeHelper::kSync);
    ASSERT(!function.IsAsyncFunction());
    ASSERT(!function.IsAsyncGenerator());
    ASSERT(!function.IsSyncGenerator());
  }

  // If the start token position is synthetic, the end token position
  // should be as well.
  function.set_end_token_pos(
      position.IsReal() ? function_node_helper.end_position_ : position);

  function.set_kernel_offset(func_node_offset);
  T.SetupFunctionParameters(Class::Handle(Z), function,
                            false,  // is_method
                            true,   // is_closure
                            &function_node_helper);
  // type_translator->SetupUnboxingInfoMetadata is not called here at the
  // moment because closures do not have unboxed parameters and return
  // value

  // Finalize function type.
  FunctionType& signature = FunctionType::Handle(Z, function.signature());
  signature ^= ClassFinalizer::FinalizeType(signature);
  function.SetSignature(signature);

  ClosureFunctionsCache::AddClosureFunctionLocked(function);

  return function.ptr();
}

FunctionPtr KernelLoader::GetClosureFunction(Thread* thread,
                                             intptr_t func_decl_offset,
                                             const Function& member_function,
                                             const Function& parent_function,
                                             const Object& closure_owner) {
  Zone* zone = thread->zone();
  Function& function = Function::Handle(zone);
  intptr_t func_node_offset = -1;

  const auto& kernel_info =
      KernelProgramInfo::Handle(zone, member_function.KernelProgramInfo());
  const auto& library_kernel_data =
      TypedDataView::Handle(zone, member_function.KernelLibrary());
  ASSERT(!library_kernel_data.IsNull());
  const intptr_t library_kernel_offset = member_function.KernelLibraryOffset();

  KernelLoader kernel_loader(kernel_info, library_kernel_data,
                             library_kernel_offset);
  {
    // TODO(alexmarkov): Use func_decl_offset as a key in ClosureFunctionsCache
    // instead of func_node_offset and avoid this reading.
    kernel_loader.helper_.SetOffset(func_decl_offset);
    kernel_loader.helper_.ReadUntilFunctionNode();
    func_node_offset = kernel_loader.helper_.ReaderOffset();

    {
      SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
      function = ClosureFunctionsCache::LookupClosureFunctionLocked(
          member_function, func_node_offset);
      if (!function.IsNull()) {
        return function.ptr();
      }
    }
  }

  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
  function = ClosureFunctionsCache::LookupClosureFunctionLocked(
      member_function, func_node_offset);
  if (function.IsNull()) {
    ActiveClassScope active_class_scope(
        &kernel_loader.active_class_,
        &Class::Handle(zone, member_function.Owner()));
    ActiveMemberScope active_member(&kernel_loader.active_class_,
                                    &member_function);
    ActiveTypeParametersScope active_type_params(
        &kernel_loader.active_class_, member_function,
        &FunctionType::Handle(zone, parent_function.signature()), zone);
    kernel_loader.helper_.SetOffset(func_decl_offset);
    function =
        kernel_loader.LoadClosureFunction(parent_function, closure_owner);
  }
  return function.ptr();
}

FunctionPtr CreateFieldInitializerFunction(Thread* thread,
                                           Zone* zone,
                                           const Field& field) {
  ASSERT(field.InitializerFunction() == Function::null());

  String& init_name = String::Handle(zone, field.name());
  init_name = Symbols::FromConcat(thread, Symbols::InitPrefix(), init_name);

  // Static field initializers are not added as members of their owning class,
  // so they must be preemptively given a patch class to avoid the meaning of
  // their kernel/token position changing during a reload. Compare
  // Class::PatchFieldsAndFunctions().
  // This might also be necessary for lazy computation of local var descriptors.
  // Compare https://codereview.chromium.org//1317753004
  const Script& script = Script::Handle(zone, field.Script());
  const Class& field_owner = Class::Handle(zone, field.Owner());
  const auto& kernel_program_info =
      KernelProgramInfo::Handle(zone, field.KernelProgramInfo());
  const PatchClass& initializer_owner = PatchClass::Handle(
      zone, PatchClass::New(field_owner, kernel_program_info, script));
  const Library& lib = Library::Handle(zone, field_owner.library());
  initializer_owner.set_kernel_library_index(lib.kernel_library_index());

  // Create a static initializer.
  FunctionType& signature = FunctionType::Handle(zone, FunctionType::New());
  const Function& initializer_fun = Function::Handle(
      zone,
      Function::New(signature, init_name, UntaggedFunction::kFieldInitializer,
                    field.is_static(),  // is_static
                    false,              // is_const
                    false,              // is_abstract
                    false,              // is_external
                    false,              // is_native
                    initializer_owner, TokenPosition::kNoSource));
  if (!field.is_static()) {
    signature.set_num_fixed_parameters(1);
    signature.set_parameter_types(
        Array::Handle(zone, Array::New(1, Heap::kOld)));
    signature.SetParameterTypeAt(
        0, AbstractType::Handle(zone, field_owner.DeclarationType()));
    initializer_fun.CreateNameArray();
    initializer_fun.SetParameterNameAt(0, Symbols::This());
  }
  signature.set_result_type(AbstractType::Handle(zone, field.type()));
  initializer_fun.set_is_reflectable(false);
  initializer_fun.set_is_inlinable(false);
  initializer_fun.set_token_pos(field.token_pos());
  initializer_fun.set_end_token_pos(field.end_token_pos());
  initializer_fun.set_accessor_field(field);
  initializer_fun.InheritKernelOffsetFrom(field);
  initializer_fun.set_is_extension_member(field.is_extension_member());
  initializer_fun.set_is_extension_type_member(
      field.is_extension_type_member());

  signature ^= ClassFinalizer::FinalizeType(signature);
  initializer_fun.SetSignature(signature);

  field.SetInitializerFunction(initializer_fun);
  return initializer_fun.ptr();
}

}  // namespace kernel
}  // namespace dart
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
