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

#include "vm/compiler/frontend/kernel_translation_helper.h"

#include "vm/class_finalizer.h"
#include "vm/compiler/aot/precompiler.h"
#include "vm/compiler/backend/flow_graph_compiler.h"
#include "vm/compiler/frontend/constant_reader.h"
#include "vm/flags.h"
#include "vm/log.h"
#include "vm/object_store.h"
#include "vm/parser.h"  // for ParsedFunction
#include "vm/symbols.h"

#define Z (zone_)
#define H (translation_helper_)
#define T (type_translator_)
#define I Isolate::Current()
#define IG IsolateGroup::Current()

namespace dart {
namespace kernel {

TranslationHelper::TranslationHelper(Thread* thread)
    : thread_(thread),
      zone_(thread->zone()),
      isolate_(thread->isolate()),
      isolate_group_(thread->isolate_group()),
      allocation_space_(Heap::kNew),
      string_offsets_(TypedData::Handle(Z)),
      string_data_(ExternalTypedData::Handle(Z)),
      canonical_names_(TypedData::Handle(Z)),
      metadata_payloads_(ExternalTypedData::Handle(Z)),
      metadata_mappings_(ExternalTypedData::Handle(Z)),
      constants_(Array::Handle(Z)),
      constants_table_(ExternalTypedData::Handle(Z)),
      info_(KernelProgramInfo::Handle(Z)),
      name_index_handle_(Smi::Handle(Z)) {}

TranslationHelper::TranslationHelper(Thread* thread, Heap::Space space)
    : thread_(thread),
      zone_(thread->zone()),
      isolate_(thread->isolate()),
      isolate_group_(thread->isolate_group()),
      allocation_space_(space),
      string_offsets_(TypedData::Handle(Z)),
      string_data_(ExternalTypedData::Handle(Z)),
      canonical_names_(TypedData::Handle(Z)),
      metadata_payloads_(ExternalTypedData::Handle(Z)),
      metadata_mappings_(ExternalTypedData::Handle(Z)),
      constants_(Array::Handle(Z)),
      constants_table_(ExternalTypedData::Handle(Z)),
      info_(KernelProgramInfo::Handle(Z)),
      name_index_handle_(Smi::Handle(Z)) {}

void TranslationHelper::Reset() {
  string_offsets_ = TypedData::null();
  string_data_ = ExternalTypedData::null();
  canonical_names_ = TypedData::null();
  metadata_payloads_ = ExternalTypedData::null();
  metadata_mappings_ = ExternalTypedData::null();
  constants_ = Array::null();
}

void TranslationHelper::InitFromScript(const Script& script) {
  const KernelProgramInfo& info =
      KernelProgramInfo::Handle(Z, script.kernel_program_info());
  if (info.IsNull()) {
    // If there is no kernel data associated with the script, then
    // do not bother initializing!.
    // This can happen with few special functions like
    // NoSuchMethodDispatcher and InvokeFieldDispatcher.
    return;
  }
  InitFromKernelProgramInfo(info);
}

void TranslationHelper::InitFromKernelProgramInfo(
    const KernelProgramInfo& info) {
  SetStringOffsets(TypedData::Handle(Z, info.string_offsets()));
  SetStringData(ExternalTypedData::Handle(Z, info.string_data()));
  SetCanonicalNames(TypedData::Handle(Z, info.canonical_names()));
  SetMetadataPayloads(ExternalTypedData::Handle(Z, info.metadata_payloads()));
  SetMetadataMappings(ExternalTypedData::Handle(Z, info.metadata_mappings()));
  SetConstants(Array::Handle(Z, info.constants()));
  SetConstantsTable(ExternalTypedData::Handle(Z, info.constants_table()));
  SetKernelProgramInfo(info);
}

GrowableObjectArrayPtr TranslationHelper::EnsurePotentialPragmaFunctions() {
  auto& funcs =
      GrowableObjectArray::Handle(Z, info_.potential_pragma_functions());
  if (funcs.IsNull()) {
    funcs = GrowableObjectArray::New(16, Heap::kNew);
    info_.set_potential_pragma_functions(funcs);
  }
  return funcs.ptr();
}

void TranslationHelper::AddPotentialExtensionLibrary(const Library& library) {
  if (potential_extension_libraries_ == nullptr) {
    potential_extension_libraries_ =
        &GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
  }
  potential_extension_libraries_->Add(library);
}

GrowableObjectArrayPtr TranslationHelper::GetPotentialExtensionLibraries() {
  if (potential_extension_libraries_ != nullptr) {
    GrowableObjectArray* result = potential_extension_libraries_;
    potential_extension_libraries_ = nullptr;
    return result->ptr();
  }
  return GrowableObjectArray::null();
}

void TranslationHelper::SetStringOffsets(const TypedData& string_offsets) {
  ASSERT(string_offsets_.IsNull());
  string_offsets_ = string_offsets.ptr();
}

void TranslationHelper::SetStringData(const ExternalTypedData& string_data) {
  ASSERT(string_data_.IsNull());
  string_data_ = string_data.ptr();
}

void TranslationHelper::SetCanonicalNames(const TypedData& canonical_names) {
  ASSERT(canonical_names_.IsNull());
  canonical_names_ = canonical_names.ptr();
}

void TranslationHelper::SetMetadataPayloads(
    const ExternalTypedData& metadata_payloads) {
  ASSERT(metadata_payloads_.IsNull());
  ASSERT(Utils::IsAligned(metadata_payloads.DataAddr(0), kWordSize));
  metadata_payloads_ = metadata_payloads.ptr();
}

void TranslationHelper::SetMetadataMappings(
    const ExternalTypedData& metadata_mappings) {
  ASSERT(metadata_mappings_.IsNull());
  metadata_mappings_ = metadata_mappings.ptr();
}

void TranslationHelper::SetConstants(const Array& constants) {
  ASSERT(constants_.IsNull() ||
         (constants.IsNull() || constants.Length() == 0));
  constants_ = constants.ptr();
}

void TranslationHelper::SetConstantsTable(
    const ExternalTypedData& constants_table) {
  ASSERT(constants_table_.IsNull());
  constants_table_ = constants_table.ptr();
}

void TranslationHelper::SetKernelProgramInfo(const KernelProgramInfo& info) {
  info_ = info.ptr();
}

intptr_t TranslationHelper::StringOffset(StringIndex index) const {
  return string_offsets_.GetUint32(index << 2);
}

intptr_t TranslationHelper::StringSize(StringIndex index) const {
  return StringOffset(StringIndex(index + 1)) - StringOffset(index);
}

uint8_t TranslationHelper::CharacterAt(StringIndex string_index,
                                       intptr_t index) {
  ASSERT(index < StringSize(string_index));
  return string_data_.GetUint8(StringOffset(string_index) + index);
}

uint8_t* TranslationHelper::StringBuffer(StringIndex string_index) const {
  // Though this implementation appears like it could be replaced by
  // string_data_.DataAddr(StringOffset(string_index)), it can't quite.  If the
  // last string in the string table is a zero length string, then the latter
  // expression will try to return the address that is one past the backing
  // store of the string_data_ table.  Though this is safe in C++ as long as the
  // address is not dereferenced, it will trigger the assert in
  // ExternalTypedData::DataAddr.
  ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0);
  return reinterpret_cast<uint8_t*>(string_data_.DataAddr(0)) +
         StringOffset(string_index);
}

bool TranslationHelper::StringEquals(StringIndex string_index,
                                     const char* other) {
  intptr_t length = strlen(other);
  if (length != StringSize(string_index)) return false;

  NoSafepointScope no_safepoint;
  return memcmp(StringBuffer(string_index), other, length) == 0;
}

NameIndex TranslationHelper::CanonicalNameParent(NameIndex name) {
  // Canonical names are pairs of 4-byte parent and string indexes, so the size
  // of an entry is 8 bytes.  The parent is biased: 0 represents the root name
  // and N+1 represents the name with index N.
  return NameIndex(static_cast<intptr_t>(canonical_names_.GetUint32(8 * name)) -
                   1);
}

StringIndex TranslationHelper::CanonicalNameString(NameIndex name) {
  return StringIndex(canonical_names_.GetUint32((8 * name) + 4));
}

bool TranslationHelper::IsAdministrative(NameIndex name) {
  // Administrative names start with '@'.
  StringIndex name_string = CanonicalNameString(name);
  return (StringSize(name_string) > 0) && (CharacterAt(name_string, 0) == '@');
}

bool TranslationHelper::IsPrivate(NameIndex name) {
  // Private names start with '_'.
  StringIndex name_string = CanonicalNameString(name);
  return (StringSize(name_string) > 0) && (CharacterAt(name_string, 0) == '_');
}

bool TranslationHelper::IsRoot(NameIndex name) {
  return name == -1;
}

bool TranslationHelper::IsLibrary(NameIndex name) {
  // Libraries are the only canonical names with the root as their parent.
  return !IsRoot(name) && IsRoot(CanonicalNameParent(name));
}

bool TranslationHelper::IsClass(NameIndex name) {
  // Classes have the library as their parent and are not an administrative
  // name starting with @.
  return !IsAdministrative(name) && !IsRoot(name) &&
         IsLibrary(CanonicalNameParent(name));
}

bool TranslationHelper::IsMember(NameIndex name) {
  return IsConstructor(name) || IsProcedure(name);
}

bool TranslationHelper::IsConstructor(NameIndex name) {
  // Constructors with private names have the import URI of the library where
  // they are visible as the parent and the string "@constructors" as the
  // parent's parent.  Constructors with non-private names have the string
  // "@constructors" as the parent.
  if (IsRoot(name)) {
    return false;
  }
  NameIndex kind = CanonicalNameParent(name);
  if (IsPrivate(name)) {
    kind = CanonicalNameParent(kind);
  }
  return StringEquals(CanonicalNameString(kind), "@constructors");
}

bool TranslationHelper::IsProcedure(NameIndex name) {
  return IsMethod(name) || IsGetter(name) || IsSetter(name) || IsFactory(name);
}

bool TranslationHelper::IsMethod(NameIndex name) {
  // Methods with private names have the import URI of the library where they
  // are visible as the parent and the string "@methods" as the parent's parent.
  // Methods with non-private names have the string "@methods" as the parent.
  if (IsRoot(name)) {
    return false;
  }
  NameIndex kind = CanonicalNameParent(name);
  if (IsPrivate(name)) {
    kind = CanonicalNameParent(kind);
  }
  return StringEquals(CanonicalNameString(kind), "@methods");
}

bool TranslationHelper::IsGetter(NameIndex name) {
  // Getters with private names have the import URI of the library where they
  // are visible as the parent and the string "@getters" as the parent's parent.
  // Getters with non-private names have the string "@getters" as the parent.
  if (IsRoot(name)) {
    return false;
  }
  NameIndex kind = CanonicalNameParent(name);
  if (IsPrivate(name)) {
    kind = CanonicalNameParent(kind);
  }
  return StringEquals(CanonicalNameString(kind), "@getters");
}

bool TranslationHelper::IsSetter(NameIndex name) {
  // Setters with private names have the import URI of the library where they
  // are visible as the parent and the string "@setters" as the parent's parent.
  // Setters with non-private names have the string "@setters" as the parent.
  if (IsRoot(name)) {
    return false;
  }
  NameIndex kind = CanonicalNameParent(name);
  if (IsPrivate(name)) {
    kind = CanonicalNameParent(kind);
  }
  return StringEquals(CanonicalNameString(kind), "@setters");
}

bool TranslationHelper::IsFactory(NameIndex name) {
  // Factories with private names have the import URI of the library where they
  // are visible as the parent and the string "@factories" as the parent's
  // parent.  Factories with non-private names have the string "@factories" as
  // the parent.
  if (IsRoot(name)) {
    return false;
  }
  NameIndex kind = CanonicalNameParent(name);
  if (IsPrivate(name)) {
    kind = CanonicalNameParent(kind);
  }
  return StringEquals(CanonicalNameString(kind), "@factories");
}

bool TranslationHelper::IsField(NameIndex name) {
  // Fields with private names have the import URI of the library where they
  // are visible as the parent and the string "@fields" as the parent's parent.
  // Fields with non-private names have the string "@fields" as the parent.
  if (IsRoot(name)) {
    return false;
  }
  NameIndex kind = CanonicalNameParent(name);
  if (IsPrivate(name)) {
    kind = CanonicalNameParent(kind);
  }
  return StringEquals(CanonicalNameString(kind), "@fields");
}

NameIndex TranslationHelper::EnclosingName(NameIndex name) {
  ASSERT(IsConstructor(name) || IsProcedure(name) || IsField(name));
  NameIndex enclosing = CanonicalNameParent(CanonicalNameParent(name));
  if (IsPrivate(name)) {
    enclosing = CanonicalNameParent(enclosing);
  }
  ASSERT(IsLibrary(enclosing) || IsClass(enclosing));
  return enclosing;
}

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

  return instance.Canonicalize(thread());
}

const String& TranslationHelper::DartString(const char* content,
                                            Heap::Space space) {
  return String::ZoneHandle(Z, String::New(content, space));
}

String& TranslationHelper::DartString(StringIndex string_index,
                                      Heap::Space space) {
  intptr_t length = StringSize(string_index);
  uint8_t* buffer = Z->Alloc<uint8_t>(length);
  {
    NoSafepointScope no_safepoint;
    memmove(buffer, StringBuffer(string_index), length);
  }
  return String::ZoneHandle(Z, String::FromUTF8(buffer, length, space));
}

String& TranslationHelper::DartString(const uint8_t* utf8_array,
                                      intptr_t len,
                                      Heap::Space space) {
  return String::ZoneHandle(Z, String::FromUTF8(utf8_array, len, space));
}

const String& TranslationHelper::DartString(
    const GrowableHandlePtrArray<const String>& pieces) {
  return String::ZoneHandle(Z, Symbols::FromConcatAll(thread_, pieces));
}

const String& TranslationHelper::DartSymbolPlain(const char* content) const {
  return String::ZoneHandle(Z, Symbols::New(thread_, content));
}

String& TranslationHelper::DartSymbolPlain(StringIndex string_index) const {
  intptr_t length = StringSize(string_index);
  uint8_t* buffer = Z->Alloc<uint8_t>(length);
  {
    NoSafepointScope no_safepoint;
    memmove(buffer, StringBuffer(string_index), length);
  }
  String& result =
      String::ZoneHandle(Z, Symbols::FromUTF8(thread_, buffer, length));
  return result;
}

const String& TranslationHelper::DartSymbolObfuscate(
    const char* content) const {
  String& result = String::ZoneHandle(Z, Symbols::New(thread_, content));
  if (IG->obfuscate()) {
    Obfuscator obfuscator(thread_, String::Handle(Z));
    result = obfuscator.Rename(result, true);
  }
  return result;
}

String& TranslationHelper::DartSymbolObfuscate(StringIndex string_index) const {
  intptr_t length = StringSize(string_index);
  uint8_t* buffer = Z->Alloc<uint8_t>(length);
  {
    NoSafepointScope no_safepoint;
    memmove(buffer, StringBuffer(string_index), length);
  }
  String& result =
      String::ZoneHandle(Z, Symbols::FromUTF8(thread_, buffer, length));
  if (IG->obfuscate()) {
    Obfuscator obfuscator(thread_, String::Handle(Z));
    result = obfuscator.Rename(result, true);
  }
  return result;
}

String& TranslationHelper::DartIdentifier(const Library& lib,
                                          StringIndex string_index) {
  String& name = DartString(string_index);
  ManglePrivateName(lib, &name);
  return name;
}

const String& TranslationHelper::DartClassName(NameIndex kernel_class) {
  ASSERT(IsClass(kernel_class));
  String& name = DartString(CanonicalNameString(kernel_class));
  return ManglePrivateName(CanonicalNameParent(kernel_class), &name);
}

const String& TranslationHelper::DartConstructorName(NameIndex constructor) {
  ASSERT(IsConstructor(constructor));
  return DartFactoryName(constructor);
}

const String& TranslationHelper::DartProcedureName(NameIndex procedure) {
  ASSERT(IsProcedure(procedure) || IsConstructor(procedure));
  if (IsSetter(procedure)) {
    return DartSetterName(procedure);
  } else if (IsGetter(procedure)) {
    return DartGetterName(procedure);
  } else if (IsFactory(procedure)) {
    return DartFactoryName(procedure);
  } else if (IsMethod(procedure)) {
    return DartMethodName(procedure);
  } else {
    ASSERT(IsConstructor(procedure));
    return DartConstructorName(procedure);
  }
}

const String& TranslationHelper::DartSetterName(NameIndex setter) {
  return DartSetterName(CanonicalNameParent(setter),
                        CanonicalNameString(setter));
}

const String& TranslationHelper::DartSetterName(NameIndex parent,
                                                StringIndex setter) {
  // The names flowing into [setter] are coming from the Kernel file:
  //   * user-defined setters: `fieldname=`
  //   * property-set expressions:  `fieldname`
  //
  // The VM uses `get:fieldname` and `set:fieldname`.
  //
  // => In order to be consistent, we remove the `=` always and adopt the VM
  //    conventions.
  intptr_t size = StringSize(setter);
  ASSERT(size > 0);
  if (CharacterAt(setter, size - 1) == '=') {
    --size;
  }
  uint8_t* buffer = Z->Alloc<uint8_t>(size);
  {
    NoSafepointScope no_safepoint;
    memmove(buffer, StringBuffer(setter), size);
  }
  String& name =
      String::ZoneHandle(Z, String::FromUTF8(buffer, size, allocation_space_));
  ManglePrivateName(parent, &name);
  name = Field::SetterSymbol(name);
  return name;
}

const String& TranslationHelper::DartGetterName(NameIndex getter) {
  return DartGetterName(CanonicalNameParent(getter),
                        CanonicalNameString(getter));
}

const String& TranslationHelper::DartGetterName(NameIndex parent,
                                                StringIndex getter) {
  String& name = DartString(getter);
  ManglePrivateName(parent, &name);
  name = Field::GetterSymbol(name);
  return name;
}

const String& TranslationHelper::DartFieldName(NameIndex field) {
  return DartFieldName(CanonicalNameParent(field), CanonicalNameString(field));
}

const String& TranslationHelper::DartFieldName(NameIndex parent,
                                               StringIndex field) {
  String& name = DartString(field);
  return ManglePrivateName(parent, &name);
}

const String& TranslationHelper::DartMethodName(NameIndex method) {
  return DartMethodName(CanonicalNameParent(method),
                        CanonicalNameString(method));
}

const String& TranslationHelper::DartMethodName(NameIndex parent,
                                                StringIndex method) {
  String& name = DartString(method);
  return ManglePrivateName(parent, &name);
}

const String& TranslationHelper::DartFactoryName(NameIndex factory) {
  ASSERT(IsConstructor(factory) || IsFactory(factory));
  GrowableHandlePtrArray<const String> pieces(Z, 3);
  pieces.Add(DartClassName(EnclosingName(factory)));
  pieces.Add(Symbols::Dot());
  // [DartMethodName] will mangle the name.
  pieces.Add(DartMethodName(factory));
  return String::ZoneHandle(Z, Symbols::FromConcatAll(thread_, pieces));
}

// TODO(https://github.com/dart-lang/sdk/issues/37517): Should emit code to
// throw a NoSuchMethodError.
static void CheckStaticLookup(const Object& target) {
  if (target.IsNull()) {
#ifndef PRODUCT
    ASSERT(IsolateGroup::Current()->HasAttemptedReload());
    Report::LongJump(LanguageError::Handle(LanguageError::New(String::Handle(
        String::New("Unimplemented handling of missing static target")))));
#else
    UNREACHABLE();
#endif
  }
}

LibraryPtr TranslationHelper::LookupLibraryByKernelLibrary(
    NameIndex kernel_library) {
  // We only use the string and don't rely on having any particular parent.
  // This ASSERT is just a sanity check.
  ASSERT(IsLibrary(kernel_library) ||
         IsAdministrative(CanonicalNameParent(kernel_library)));
  {
    name_index_handle_ = Smi::New(kernel_library);
    LibraryPtr raw_lib = info_.LookupLibrary(thread_, name_index_handle_);
    NoSafepointScope no_safepoint_scope(thread_);
    if (raw_lib != Library::null()) {
      return raw_lib;
    }
  }

  const String& library_name =
      DartSymbolPlain(CanonicalNameString(kernel_library));
  ASSERT(!library_name.IsNull());
  const Library& library =
      Library::Handle(Z, Library::LookupLibrary(thread_, library_name));
  CheckStaticLookup(library);
  name_index_handle_ = Smi::New(kernel_library);
  return info_.InsertLibrary(thread_, name_index_handle_, library);
}

ClassPtr TranslationHelper::LookupClassByKernelClass(NameIndex kernel_class) {
  ASSERT(IsClass(kernel_class));
  {
    name_index_handle_ = Smi::New(kernel_class);
    ClassPtr raw_class = info_.LookupClass(thread_, name_index_handle_);
    NoSafepointScope no_safepoint_scope(thread_);
    if (raw_class != Class::null()) {
      return raw_class;
    }
  }

  const String& class_name = DartClassName(kernel_class);
  NameIndex kernel_library = CanonicalNameParent(kernel_class);
  Library& library =
      Library::Handle(Z, LookupLibraryByKernelLibrary(kernel_library));
  ASSERT(!library.IsNull());
  const Class& klass =
      Class::Handle(Z, library.LookupClassAllowPrivate(class_name));
  CheckStaticLookup(klass);
  ASSERT(!klass.IsNull());
  name_index_handle_ = Smi::New(kernel_class);
  return info_.InsertClass(thread_, name_index_handle_, klass);
}

FieldPtr TranslationHelper::LookupFieldByKernelField(NameIndex kernel_field) {
  ASSERT(IsField(kernel_field));
  NameIndex enclosing = EnclosingName(kernel_field);

  Class& klass = Class::Handle(Z);
  if (IsLibrary(enclosing)) {
    Library& library =
        Library::Handle(Z, LookupLibraryByKernelLibrary(enclosing));
    klass = library.toplevel_class();
    CheckStaticLookup(klass);
  } else {
    ASSERT(IsClass(enclosing));
    klass = LookupClassByKernelClass(enclosing);
  }
  Field& field = Field::Handle(
      Z, klass.LookupFieldAllowPrivate(
             DartSymbolObfuscate(CanonicalNameString(kernel_field))));
  CheckStaticLookup(field);
  return field.ptr();
}

FieldPtr TranslationHelper::LookupFieldByKernelGetterOrSetter(
    NameIndex kernel_field,
    bool required) {
  ASSERT(IsGetter(kernel_field) || IsSetter(kernel_field));
  NameIndex enclosing = EnclosingName(kernel_field);

  Class& klass = Class::Handle(Z);
  if (IsLibrary(enclosing)) {
    Library& library =
        Library::Handle(Z, LookupLibraryByKernelLibrary(enclosing));
    klass = library.toplevel_class();
    CheckStaticLookup(klass);
  } else {
    ASSERT(IsClass(enclosing));
    klass = LookupClassByKernelClass(enclosing);
  }
  Field& field = Field::Handle(
      Z, klass.LookupFieldAllowPrivate(
             DartSymbolObfuscate(CanonicalNameString(kernel_field))));
  if (required) {
    CheckStaticLookup(field);
  }
  return field.ptr();
}

FunctionPtr TranslationHelper::LookupStaticMethodByKernelProcedure(
    NameIndex procedure,
    bool required) {
  const String& procedure_name = DartProcedureName(procedure);

  // The parent is either a library or a class (in which case the procedure is a
  // static method).
  NameIndex enclosing = EnclosingName(procedure);
  if (IsLibrary(enclosing)) {
    Library& library =
        Library::Handle(Z, LookupLibraryByKernelLibrary(enclosing));
    Function& function =
        Function::Handle(Z, library.LookupFunctionAllowPrivate(procedure_name));
    if (required) {
      CheckStaticLookup(function);
    }
    return function.ptr();
  } else {
    ASSERT(IsClass(enclosing));
    Class& klass = Class::Handle(Z, LookupClassByKernelClass(enclosing));
    const auto& error = klass.EnsureIsFinalized(thread_);
    ASSERT(error == Error::null());
    Function& function = Function::ZoneHandle(
        Z, klass.LookupFunctionAllowPrivate(procedure_name));
    if (required) {
      CheckStaticLookup(function);
    }
    return function.ptr();
  }
}

FunctionPtr TranslationHelper::LookupConstructorByKernelConstructor(
    NameIndex constructor) {
  ASSERT(IsConstructor(constructor));
  Class& klass =
      Class::Handle(Z, LookupClassByKernelClass(EnclosingName(constructor)));
  CheckStaticLookup(klass);
  return LookupConstructorByKernelConstructor(klass, constructor);
}

FunctionPtr TranslationHelper::LookupConstructorByKernelConstructor(
    const Class& owner,
    NameIndex constructor) {
  ASSERT(IsConstructor(constructor));
  const auto& error = owner.EnsureIsFinalized(thread_);
  ASSERT(error == Error::null());
  Function& function = Function::Handle(
      Z, owner.LookupConstructorAllowPrivate(DartConstructorName(constructor)));
  CheckStaticLookup(function);
  return function.ptr();
}

FunctionPtr TranslationHelper::LookupConstructorByKernelConstructor(
    const Class& owner,
    StringIndex constructor_name) {
  GrowableHandlePtrArray<const String> pieces(Z, 3);
  pieces.Add(String::Handle(Z, owner.Name()));
  pieces.Add(Symbols::Dot());
  String& name = DartSymbolPlain(constructor_name);
  pieces.Add(ManglePrivateName(Library::Handle(owner.library()), &name));

  String& new_name =
      String::ZoneHandle(Z, Symbols::FromConcatAll(thread_, pieces));
  const auto& error = owner.EnsureIsFinalized(thread_);
  ASSERT(error == Error::null());
  FunctionPtr function = owner.LookupConstructorAllowPrivate(new_name);
  ASSERT(function != Object::null());
  return function;
}

FunctionPtr TranslationHelper::LookupMethodByMember(NameIndex target,
                                                    const String& method_name) {
  NameIndex kernel_class = EnclosingName(target);
  Class& klass = Class::Handle(Z, LookupClassByKernelClass(kernel_class));
  Function& function = Function::Handle(Z);
  if (klass.EnsureIsFinalized(thread_) == Error::null()) {
    function = klass.LookupFunctionAllowPrivate(method_name);
  }
#ifdef DEBUG
  if (function.IsNull()) {
    THR_Print("Unable to find \'%s\' in %s\n", method_name.ToCString(),
              klass.ToCString());
  }
#endif
  CheckStaticLookup(function);
  ASSERT(!function.IsNull());
  return function.ptr();
}

FunctionPtr TranslationHelper::LookupDynamicFunction(const Class& klass,
                                                     const String& name) {
  // Search the superclass chain for the selector.
  Class& iterate_klass = Class::Handle(Z, klass.ptr());
  while (!iterate_klass.IsNull()) {
    FunctionPtr function =
        iterate_klass.LookupDynamicFunctionAllowPrivate(name);
    if (function != Object::null()) {
      return function;
    }
    iterate_klass = iterate_klass.SuperClass();
  }
  return Function::null();
}

Type& TranslationHelper::GetDeclarationType(const Class& klass) {
  ASSERT(!klass.IsNull());
  // Forward expression evaluation class to a real class when
  // creating types.
  if (GetExpressionEvaluationClass().ptr() == klass.ptr()) {
    ASSERT(GetExpressionEvaluationRealClass().ptr() != klass.ptr());
    return GetDeclarationType(GetExpressionEvaluationRealClass());
  }
  ASSERT(klass.id() != kIllegalCid);
  // Note that if cls is _Closure, the returned type will be _Closure,
  // and not the signature type.
  Type& type = Type::ZoneHandle(Z);
  if (klass.is_type_finalized()) {
    type = klass.DeclarationType();
  } else {
    // Note that the type argument vector is not yet extended.
    TypeArguments& type_args = TypeArguments::Handle(Z);
    const intptr_t num_type_params = klass.NumTypeParameters();
    if (num_type_params > 0) {
      type_args = TypeArguments::New(num_type_params);
      TypeParameter& type_param = TypeParameter::Handle();
      for (intptr_t i = 0; i < num_type_params; i++) {
        type_param = klass.TypeParameterAt(i);
        ASSERT(type_param.bound() != AbstractType::null());
        type_args.SetTypeAt(i, type_param);
      }
    }
    type = Type::New(klass, type_args, Nullability::kNonNullable);
  }
  return type;
}

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

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

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

void TranslationHelper::ReportError(const char* format, ...) {
  const Script& null_script = Script::Handle(Z);

  va_list args;
  va_start(args, format);
  Report::MessageV(Report::kError, null_script, TokenPosition::kNoSource,
                   Report::AtLocation, format, args);
  va_end(args);
  UNREACHABLE();
}

void TranslationHelper::ReportError(const Script& script,
                                    const TokenPosition position,
                                    const char* format,
                                    ...) {
  va_list args;
  va_start(args, format);
  Report::MessageV(Report::kError, script, position, Report::AtLocation, format,
                   args);
  va_end(args);
  UNREACHABLE();
}

void TranslationHelper::ReportError(const Error& prev_error,
                                    const char* format,
                                    ...) {
  const Script& null_script = Script::Handle(Z);

  va_list args;
  va_start(args, format);
  Report::LongJumpV(prev_error, null_script, TokenPosition::kNoSource, format,
                    args);
  va_end(args);
  UNREACHABLE();
}

void TranslationHelper::ReportError(const Error& prev_error,
                                    const Script& script,
                                    const TokenPosition position,
                                    const char* format,
                                    ...) {
  va_list args;
  va_start(args, format);
  Report::LongJumpV(prev_error, script, position, format, args);
  va_end(args);
  UNREACHABLE();
}

String& TranslationHelper::ManglePrivateName(NameIndex parent,
                                             String* name_to_modify,
                                             bool symbolize,
                                             bool obfuscate) {
  if (name_to_modify->Length() >= 1 && name_to_modify->CharAt(0) == '_') {
    const Library& library =
        Library::Handle(Z, LookupLibraryByKernelLibrary(parent));
    *name_to_modify = library.PrivateName(*name_to_modify);
    if (obfuscate && IG->obfuscate()) {
      const String& library_key = String::Handle(library.private_key());
      Obfuscator obfuscator(thread_, library_key);
      *name_to_modify = obfuscator.Rename(*name_to_modify);
    }
  } else if (symbolize) {
    *name_to_modify = Symbols::New(thread_, *name_to_modify);
    if (obfuscate && IG->obfuscate()) {
      const String& library_key = String::Handle();
      Obfuscator obfuscator(thread_, library_key);
      *name_to_modify = obfuscator.Rename(*name_to_modify);
    }
  }
  return *name_to_modify;
}

String& TranslationHelper::ManglePrivateName(const Library& library,
                                             String* name_to_modify,
                                             bool symbolize,
                                             bool obfuscate) {
  if (name_to_modify->Length() >= 1 && name_to_modify->CharAt(0) == '_' &&
      !library.IsNull()) {
    *name_to_modify = library.PrivateName(*name_to_modify);
    if (obfuscate && IG->obfuscate()) {
      const String& library_key = String::Handle(library.private_key());
      Obfuscator obfuscator(thread_, library_key);
      *name_to_modify = obfuscator.Rename(*name_to_modify);
    }
  } else if (symbolize) {
    *name_to_modify = Symbols::New(thread_, *name_to_modify);
    if (obfuscate && IG->obfuscate()) {
      const String& library_key = String::Handle();
      Obfuscator obfuscator(thread_, library_key);
      *name_to_modify = obfuscator.Rename(*name_to_modify);
    }
  }
  return *name_to_modify;
}

void FunctionNodeHelper::ReadUntilExcluding(Field field) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    case kStart: {
      Tag tag = helper_->ReadTag();  // read tag.
      ASSERT(tag == kFunctionNode);
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kPosition:
      position_ = helper_->ReadPosition();  // read position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kEndPosition:
      end_position_ = helper_->ReadPosition();  // read end position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kAsyncMarker:
      async_marker_ = static_cast<AsyncMarker>(helper_->ReadByte());
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kDartAsyncMarker:
      dart_async_marker_ = static_cast<AsyncMarker>(
          helper_->ReadByte());  // read dart async marker.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kTypeParameters:
      helper_->SkipTypeParametersList();  // read type parameters.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kTotalParameterCount:
      total_parameter_count_ =
          helper_->ReadUInt();  // read total parameter count.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kRequiredParameterCount:
      required_parameter_count_ =
          helper_->ReadUInt();  // read required parameter count.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kPositionalParameters:
      helper_->SkipListOfVariableDeclarations();  // read positionals.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kNamedParameters:
      helper_->SkipListOfVariableDeclarations();  // read named.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kReturnType:
      helper_->SkipDartType();  // read return type.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kFutureValueType:
      helper_->SkipOptionalDartType();  // read future value type.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kBody:
      if (helper_->ReadTag() == kSomething)
        helper_->SkipStatement();  // read body.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kEnd:
      return;
  }
}

void TypeParameterHelper::ReadUntilExcluding(Field field) {
  for (; next_read_ < field; ++next_read_) {
    switch (next_read_) {
      case kFlags:
        flags_ = helper_->ReadFlags();
        break;
      case kAnnotations:
        helper_->SkipListOfExpressions();  // read annotations.
        break;
      case kVariance:
        helper_->ReadVariance();
        break;
      case kName:
        name_index_ = helper_->ReadStringReference();  // read name index.
        break;
      case kBound:
        helper_->SkipDartType();
        break;
      case kDefaultType:
        helper_->SkipDartType();
        break;
      case kEnd:
        return;
    }
  }
}

void VariableDeclarationHelper::ReadUntilExcluding(Field field) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    case kPosition:
      position_ = helper_->ReadPosition();  // read position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kEqualPosition:
      equals_position_ = helper_->ReadPosition();  // read equals position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kAnnotations:
      annotation_count_ = helper_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < annotation_count_; ++i) {
        helper_->SkipExpression();  // read ith expression.
      }
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kFlags:
      flags_ = helper_->ReadUInt();
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kNameIndex:
      name_index_ = helper_->ReadStringReference();  // read name index.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kType:
      helper_->SkipDartType();  // read type.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kInitializer:
      if (helper_->ReadTag() == kSomething)
        helper_->SkipExpression();  // read initializer.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kEnd:
      return;
  }
}

FieldHelper::FieldHelper(KernelReaderHelper* helper, intptr_t offset)
    : helper_(helper), next_read_(kStart) {
  helper_->SetOffset(offset);
}

void FieldHelper::ReadUntilExcluding(Field field) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    case kStart: {
      Tag tag = helper_->ReadTag();  // read tag.
      ASSERT(tag == kField);
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kCanonicalNameField:
      canonical_name_field_ =
          helper_->ReadCanonicalNameReference();  // read canonical_name_field.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kCanonicalNameGetter:
      canonical_name_getter_ =
          helper_->ReadCanonicalNameReference();  // read canonical_name_getter.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kCanonicalNameSetter:
      canonical_name_setter_ =
          helper_->ReadCanonicalNameReference();  // read canonical_name_setter.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kSourceUriIndex:
      source_uri_index_ = helper_->ReadUInt();  // read source_uri_index.
      helper_->set_current_script_id(source_uri_index_);
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kPosition:
      position_ = helper_->ReadPosition();  // read position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kEndPosition:
      end_position_ = helper_->ReadPosition();  // read end position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kFlags:
      flags_ = helper_->ReadUInt();
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kName:
      helper_->SkipName();  // read name.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kAnnotations: {
      annotation_count_ = helper_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < annotation_count_; ++i) {
        helper_->SkipExpression();  // read ith expression.
      }
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kType:
      helper_->SkipDartType();  // read type.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kInitializer:
      if (helper_->ReadTag() == kSomething) {
        helper_->SkipExpression();  // read initializer.
      }
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kEnd:
      return;
  }
}

void ProcedureHelper::ReadUntilExcluding(Field field) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    case kStart: {
      Tag tag = helper_->ReadTag();  // read tag.
      ASSERT(tag == kProcedure);
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kCanonicalName:
      canonical_name_ =
          helper_->ReadCanonicalNameReference();  // read canonical_name.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kSourceUriIndex:
      source_uri_index_ = helper_->ReadUInt();  // read source_uri_index.
      helper_->set_current_script_id(source_uri_index_);
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kStartPosition:
      start_position_ = helper_->ReadPosition();  // read position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kPosition:
      position_ = helper_->ReadPosition();  // read position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kEndPosition:
      end_position_ = helper_->ReadPosition();  // read end position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kKind:
      kind_ = static_cast<Kind>(helper_->ReadByte());
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kStubKind:
      stub_kind_ = static_cast<StubKind>(helper_->ReadByte());
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kFlags:
      flags_ = helper_->ReadUInt();
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kName:
      helper_->SkipName();  // read name.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kAnnotations: {
      annotation_count_ = helper_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < annotation_count_; ++i) {
        helper_->SkipExpression();  // read ith expression.
      }
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kStubTarget:
      if (stub_kind_ == kConcreteForwardingStubKind) {
        concrete_forwarding_stub_target_ =
            helper_->ReadCanonicalNameReference();
      } else {
        helper_->ReadCanonicalNameReference();
      }
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kSignatureType:
      helper_->SkipOptionalDartType();  // read signature type.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kFunction:
      helper_->SkipFunctionNode();  // read function node.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kEnd:
      return;
  }
}

void ConstructorHelper::ReadUntilExcluding(Field field) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    case kStart: {
      Tag tag = helper_->ReadTag();  // read tag.
      ASSERT(tag == kConstructor);
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kCanonicalName:
      canonical_name_ =
          helper_->ReadCanonicalNameReference();  // read canonical_name.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kSourceUriIndex:
      source_uri_index_ = helper_->ReadUInt();  // read source_uri_index.
      helper_->set_current_script_id(source_uri_index_);
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kStartPosition:
      start_position_ = helper_->ReadPosition();  // read position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kPosition:
      position_ = helper_->ReadPosition();  // read position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kEndPosition:
      end_position_ = helper_->ReadPosition();  // read end position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kFlags:
      flags_ = helper_->ReadFlags();
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kName:
      helper_->SkipName();  // read name.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kAnnotations: {
      annotation_count_ = helper_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < annotation_count_; ++i) {
        helper_->SkipExpression();  // read ith expression.
      }
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kFunction:
      helper_->SkipFunctionNode();  // read function.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kInitializers: {
      intptr_t list_length =
          helper_->ReadListLength();  // read initializers list length.
      for (intptr_t i = 0; i < list_length; i++) {
        helper_->SkipInitializer();
      }
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kEnd:
      return;
  }
}

void ClassHelper::ReadUntilExcluding(Field field) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    case kStart: {
      Tag tag = helper_->ReadTag();  // read tag.
      ASSERT(tag == kClass);
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kCanonicalName:
      canonical_name_ =
          helper_->ReadCanonicalNameReference();  // read canonical_name.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kSourceUriIndex:
      source_uri_index_ = helper_->ReadUInt();  // read source_uri_index.
      helper_->set_current_script_id(source_uri_index_);
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kStartPosition:
      start_position_ = helper_->ReadPosition();  // read position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kPosition:
      position_ = helper_->ReadPosition();  // read position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kEndPosition:
      end_position_ = helper_->ReadPosition();  // read end position.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kFlags:
      flags_ = helper_->ReadFlags();  // read flags.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kNameIndex:
      name_index_ = helper_->ReadStringReference();  // read name index.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kAnnotations: {
      annotation_count_ = helper_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < annotation_count_; ++i) {
        helper_->SkipExpression();  // read ith expression.
      }
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kTypeParameters:
      helper_->SkipTypeParametersList();  // read type parameters.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kSuperClass: {
      Tag type_tag = helper_->ReadTag();  // read super class type (part 1).
      if (type_tag == kSomething) {
        helper_->SkipDartType();  // read super class type (part 2).
      }
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kMixinType: {
      Tag type_tag = helper_->ReadTag();  // read mixin type (part 1).
      if (type_tag == kSomething) {
        helper_->SkipDartType();  // read mixin type (part 2).
      }
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kImplementedClasses:
      helper_->SkipListOfDartTypes();  // read implemented_classes.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kFields: {
      intptr_t list_length =
          helper_->ReadListLength();  // read fields list length.
      for (intptr_t i = 0; i < list_length; i++) {
        FieldHelper field_helper(helper_);
        field_helper.ReadUntilExcluding(FieldHelper::kEnd);  // read field.
      }
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kConstructors: {
      intptr_t list_length =
          helper_->ReadListLength();  // read constructors list length.
      for (intptr_t i = 0; i < list_length; i++) {
        ConstructorHelper constructor_helper(helper_);
        constructor_helper.ReadUntilExcluding(
            ConstructorHelper::kEnd);  // read constructor.
      }
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kProcedures: {
      procedure_count_ = helper_->ReadListLength();  // read procedures #.
      for (intptr_t i = 0; i < procedure_count_; i++) {
        ProcedureHelper procedure_helper(helper_);
        procedure_helper.ReadUntilExcluding(
            ProcedureHelper::kEnd);  // read procedure.
      }
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kClassIndex:
      // Read class index.
      for (intptr_t i = 0; i < procedure_count_; ++i) {
        helper_->reader_.ReadUInt32();
      }
      helper_->reader_.ReadUInt32();
      helper_->reader_.ReadUInt32();
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kEnd:
      return;
  }
}

void LibraryHelper::ReadUntilExcluding(Field field) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    // Note that this (up to canonical name) needs to be kept in sync with
    // "library_canonical_name" (currently in "kernel_loader.h").
    case kFlags: {
      flags_ = helper_->ReadFlags();
      if (++next_read_ == field) return;
      FALL_THROUGH;
    }
    case kLanguageVersion: {
      helper_->ReadUInt();  // Read major language version.
      helper_->ReadUInt();  // Read minor language version.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    }
    case kCanonicalName:
      canonical_name_ =
          helper_->ReadCanonicalNameReference();  // read canonical_name.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kName:
      name_index_ = helper_->ReadStringReference();  // read name index.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kSourceUriIndex:
      source_uri_index_ = helper_->ReadUInt();  // read source_uri_index.
      helper_->set_current_script_id(source_uri_index_);
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kProblemsAsJson: {
      intptr_t length = helper_->ReadUInt();  // read length of table.
      for (intptr_t i = 0; i < length; ++i) {
        helper_->SkipBytes(helper_->ReadUInt());  // read strings.
      }
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kAnnotations:
      helper_->SkipListOfExpressions();  // read annotations.
      if (++next_read_ == field) return;
      FALL_THROUGH;
    case kDependencies: {
      intptr_t dependency_count = helper_->ReadUInt();  // read list length.
      for (intptr_t i = 0; i < dependency_count; ++i) {
        helper_->SkipLibraryDependency();
      }
      if (++next_read_ == field) return;
    }
      return;
  }
}

void LibraryDependencyHelper::ReadUntilExcluding(Field field) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    case kFileOffset: {
      helper_->ReadPosition();
      if (++next_read_ == field) return;
      FALL_THROUGH;
    }
    case kFlags: {
      flags_ = helper_->ReadFlags();
      if (++next_read_ == field) return;
      FALL_THROUGH;
    }
    case kAnnotations: {
      annotation_count_ = helper_->ReadListLength();
      for (intptr_t i = 0; i < annotation_count_; ++i) {
        helper_->SkipExpression();  // read ith expression.
      }
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kTargetLibrary: {
      target_library_canonical_name_ = helper_->ReadCanonicalNameReference();
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kName: {
      name_index_ = helper_->ReadStringReference();
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kCombinators: {
      intptr_t count = helper_->ReadListLength();
      for (intptr_t i = 0; i < count; ++i) {
        // Skip flags
        helper_->SkipBytes(1);
        // Skip list of names.
        helper_->SkipListOfStrings();
      }
      if (++next_read_ == field) return;
    }
      FALL_THROUGH;
    case kEnd:
      return;
  }
}

#if defined(DEBUG)

void MetadataHelper::VerifyMetadataMappings(
    const ExternalTypedData& metadata_mappings) {
  const intptr_t kUInt32Size = 4;
  Reader reader(metadata_mappings);
  if (reader.size() == 0) {
    return;
  }

  // Scan through metadata mappings in reverse direction.

  // Read metadataMappings length.
  intptr_t offset = reader.size() - kUInt32Size;
  const intptr_t metadata_num = reader.ReadUInt32At(offset);

  if (metadata_num == 0) {
    ASSERT(metadata_mappings.LengthInBytes() == kUInt32Size);
    return;
  }

  // Read metadataMappings elements.
  for (intptr_t i = 0; i < metadata_num; ++i) {
    // Read nodeOffsetToMetadataOffset length.
    offset -= kUInt32Size;
    const intptr_t mappings_num = reader.ReadUInt32At(offset);

    // Skip nodeOffsetToMetadataOffset.
    offset -= mappings_num * 2 * kUInt32Size;

    // Verify that node offsets are sorted.
    intptr_t prev_node_offset = -1;
    reader.set_offset(offset);
    for (intptr_t j = 0; j < mappings_num; ++j) {
      const intptr_t node_offset = reader.ReadUInt32();
      const intptr_t md_offset = reader.ReadUInt32();

      ASSERT(node_offset >= 0 && md_offset >= 0);
      ASSERT(node_offset > prev_node_offset);
      prev_node_offset = node_offset;
    }

    // Skip tag.
    offset -= kUInt32Size;
  }
}

#endif  // defined(DEBUG)

MetadataHelper::MetadataHelper(KernelReaderHelper* helper,
                               const char* tag,
                               bool precompiler_only)
    : helper_(helper),
      translation_helper_(helper->translation_helper_),
      tag_(tag),
      mappings_scanned_(false),
      precompiler_only_(precompiler_only),
      mappings_offset_(0),
      mappings_num_(0),
      last_node_offset_(0),
      last_mapping_index_(0) {}

void MetadataHelper::SetMetadataMappings(intptr_t mappings_offset,
                                         intptr_t mappings_num) {
  ASSERT((mappings_offset_ == 0) && (mappings_num_ == 0));
  ASSERT((mappings_offset != 0) && (mappings_num != 0));
  mappings_offset_ = mappings_offset;
  mappings_num_ = mappings_num;
  last_node_offset_ = kIntptrMax;
  last_mapping_index_ = 0;
}

void MetadataHelper::ScanMetadataMappings() {
  const intptr_t kUInt32Size = 4;
  Reader reader(H.metadata_mappings());
  if (reader.size() == 0) {
    return;
  }

  // Scan through metadata mappings in reverse direction.

  // Read metadataMappings length.
  intptr_t offset = reader.size() - kUInt32Size;
  uint32_t metadata_num = reader.ReadUInt32At(offset);

  if (metadata_num == 0) {
    ASSERT(H.metadata_mappings().LengthInBytes() == kUInt32Size);
    return;
  }

  // Read metadataMappings elements.
  for (uint32_t i = 0; i < metadata_num; ++i) {
    // Read nodeOffsetToMetadataOffset length.
    offset -= kUInt32Size;
    uint32_t mappings_num = reader.ReadUInt32At(offset);

    // Skip nodeOffsetToMetadataOffset and read tag.
    offset -= mappings_num * 2 * kUInt32Size + kUInt32Size;
    StringIndex tag = StringIndex(reader.ReadUInt32At(offset));

    if (mappings_num == 0) {
      continue;
    }

    if (H.StringEquals(tag, tag_)) {
      if ((!FLAG_precompiled_mode) && precompiler_only_) {
        FATAL1("%s metadata is allowed in precompiled mode only", tag_);
      }
      SetMetadataMappings(offset + kUInt32Size, mappings_num);
      return;
    }
  }
}

intptr_t MetadataHelper::FindMetadataMapping(intptr_t node_offset) {
  const intptr_t kUInt32Size = 4;
  ASSERT(mappings_num_ > 0);

  Reader reader(H.metadata_mappings());

  intptr_t left = 0;
  intptr_t right = mappings_num_ - 1;
  while (left < right) {
    intptr_t mid = ((right - left) / 2) + left;
    intptr_t mid_node_offset =
        reader.ReadUInt32At(mappings_offset_ + mid * 2 * kUInt32Size);

    if (node_offset < mid_node_offset) {
      right = mid - 1;
    } else if (node_offset > mid_node_offset) {
      left = mid + 1;
    } else {
      return mid;  // Exact match found.
    }
  }
  ASSERT((0 <= left) && (left <= mappings_num_));

  // Approximate match is found. Make sure it has an offset greater or equal
  // to the given node offset.
  if (left < mappings_num_) {
    intptr_t found_node_offset =
        reader.ReadUInt32At(mappings_offset_ + left * 2 * kUInt32Size);

    if (found_node_offset < node_offset) {
      ++left;
    }
  }
  ASSERT((left == mappings_num_) ||
         static_cast<intptr_t>(reader.ReadUInt32At(
             mappings_offset_ + left * 2 * kUInt32Size)) >= node_offset);

  return left;
}

intptr_t MetadataHelper::GetNextMetadataPayloadOffset(intptr_t node_offset) {
  if (!mappings_scanned_) {
    ScanMetadataMappings();
    mappings_scanned_ = true;
  }

  if (mappings_num_ == 0) {
    return -1;  // No metadata.
  }

  node_offset += helper_->data_program_offset_;

  // Nodes are parsed in linear order most of the time, so do the search
  // only if looking back.
  if (node_offset < last_node_offset_) {
    last_mapping_index_ = FindMetadataMapping(node_offset);
  }

  intptr_t index = last_mapping_index_;
  intptr_t mapping_node_offset = 0;
  intptr_t mapping_md_offset = -1;

  Reader reader(H.metadata_mappings());
  const intptr_t kUInt32Size = 4;
  reader.set_offset(mappings_offset_ + index * 2 * kUInt32Size);

  for (; index < mappings_num_; ++index) {
    mapping_node_offset = reader.ReadUInt32();
    mapping_md_offset = reader.ReadUInt32();

    if (mapping_node_offset >= node_offset) {
      break;
    }
  }

  last_mapping_index_ = index;
  last_node_offset_ = node_offset;

  if ((index < mappings_num_) && (mapping_node_offset == node_offset)) {
    ASSERT(mapping_md_offset >= 0);
    return mapping_md_offset;
  } else {
    return -1;
  }
}

intptr_t MetadataHelper::GetComponentMetadataPayloadOffset() {
  const intptr_t kComponentNodeOffset = 0;
  return GetNextMetadataPayloadOffset(kComponentNodeOffset -
                                      helper_->data_program_offset_);
}

DirectCallMetadataHelper::DirectCallMetadataHelper(KernelReaderHelper* helper)
    : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}

bool DirectCallMetadataHelper::ReadMetadata(intptr_t node_offset,
                                            NameIndex* target_name,
                                            bool* check_receiver_for_null) {
  intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
  if (md_offset < 0) {
    return false;
  }

  AlternativeReadingScopeWithNewData alt(&helper_->reader_,
                                         &H.metadata_payloads(), md_offset);

  *target_name = helper_->ReadCanonicalNameReference();
  *check_receiver_for_null = helper_->ReadBool();
  return true;
}

DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForPropertyGet(
    intptr_t node_offset) {
  NameIndex kernel_name;
  bool check_receiver_for_null = false;
  if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) {
    return DirectCallMetadata(Function::null_function(), false);
  }

  if (H.IsProcedure(kernel_name) && !H.IsGetter(kernel_name)) {
    // Tear-off. Use method extractor as direct call target.
    const String& method_name = H.DartMethodName(kernel_name);
    const Function& target_method = Function::ZoneHandle(
        helper_->zone_, H.LookupMethodByMember(kernel_name, method_name));
    const String& getter_name = H.DartGetterName(kernel_name);
    return DirectCallMetadata(
        Function::ZoneHandle(helper_->zone_,
                             target_method.GetMethodExtractor(getter_name)),
        check_receiver_for_null);
  } else {
    const String& getter_name = H.DartGetterName(kernel_name);
    const Function& target = Function::ZoneHandle(
        helper_->zone_, H.LookupMethodByMember(kernel_name, getter_name));
    ASSERT(target.IsGetterFunction() || target.IsImplicitGetterFunction());
    return DirectCallMetadata(target, check_receiver_for_null);
  }
}

DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForPropertySet(
    intptr_t node_offset) {
  NameIndex kernel_name;
  bool check_receiver_for_null = false;
  if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) {
    return DirectCallMetadata(Function::null_function(), false);
  }

  const String& method_name = H.DartSetterName(kernel_name);
  const Function& target = Function::ZoneHandle(
      helper_->zone_, H.LookupMethodByMember(kernel_name, method_name));
  ASSERT(target.IsSetterFunction() || target.IsImplicitSetterFunction());

  return DirectCallMetadata(target, check_receiver_for_null);
}

DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForMethodInvocation(
    intptr_t node_offset) {
  NameIndex kernel_name;
  bool check_receiver_for_null = false;
  if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) {
    return DirectCallMetadata(Function::null_function(), false);
  }

  const String& method_name = H.DartProcedureName(kernel_name);
  const Function& target = Function::ZoneHandle(
      helper_->zone_, H.LookupMethodByMember(kernel_name, method_name));

  return DirectCallMetadata(target, check_receiver_for_null);
}

InferredTypeMetadataHelper::InferredTypeMetadataHelper(
    KernelReaderHelper* helper,
    ConstantReader* constant_reader)
    : MetadataHelper(helper, tag(), /* precompiler_only = */ true),
      constant_reader_(constant_reader) {}

InferredTypeMetadata InferredTypeMetadataHelper::GetInferredType(
    intptr_t node_offset,
    bool read_constant) {
  const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
  if (md_offset < 0) {
    return InferredTypeMetadata(kDynamicCid,
                                InferredTypeMetadata::kFlagNullable);
  }

  AlternativeReadingScopeWithNewData alt(&helper_->reader_,
                                         &H.metadata_payloads(), md_offset);

  const NameIndex kernel_name = helper_->ReadCanonicalNameReference();
  const uint8_t flags = helper_->ReadByte();

  const Object* constant_value = &Object::null_object();
  if ((flags & InferredTypeMetadata::kFlagConstant) != 0) {
    const intptr_t constant_index = helper_->ReadUInt();
    if (read_constant) {
      constant_value = &Object::ZoneHandle(
          H.zone(), constant_reader_->ReadConstant(constant_index));
    }
  }

  if (H.IsRoot(kernel_name)) {
    ASSERT((flags & InferredTypeMetadata::kFlagConstant) == 0);
    return InferredTypeMetadata(kDynamicCid, flags);
  }

  const Class& klass =
      Class::Handle(helper_->zone_, H.LookupClassByKernelClass(kernel_name));
  ASSERT(!klass.IsNull());

  intptr_t cid = klass.id();
  if (cid == kClosureCid) {
    // VM uses more specific function types and doesn't expect instances of
    // _Closure class, so inferred _Closure class doesn't make sense for the VM.
    cid = kDynamicCid;
  }

  return InferredTypeMetadata(cid, flags, *constant_value);
}

void ProcedureAttributesMetadata::InitializeFromFlags(uint8_t flags) {
  const int kMethodOrSetterCalledDynamicallyBit = 1 << 0;
  const int kNonThisUsesBit = 1 << 1;
  const int kTearOffUsesBit = 1 << 2;
  const int kThisUsesBit = 1 << 3;
  const int kGetterCalledDynamicallyBit = 1 << 4;

  method_or_setter_called_dynamically =
      (flags & kMethodOrSetterCalledDynamicallyBit) != 0;
  getter_called_dynamically = (flags & kGetterCalledDynamicallyBit) != 0;
  has_this_uses = (flags & kThisUsesBit) != 0;
  has_non_this_uses = (flags & kNonThisUsesBit) != 0;
  has_tearoff_uses = (flags & kTearOffUsesBit) != 0;
}

ProcedureAttributesMetadataHelper::ProcedureAttributesMetadataHelper(
    KernelReaderHelper* helper)
    : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}

bool ProcedureAttributesMetadataHelper::ReadMetadata(
    intptr_t node_offset,
    ProcedureAttributesMetadata* metadata) {
  intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
  if (md_offset < 0) {
    return false;
  }

  AlternativeReadingScopeWithNewData alt(&helper_->reader_,
                                         &H.metadata_payloads(), md_offset);

  const uint8_t flags = helper_->ReadByte();
  metadata->InitializeFromFlags(flags);
  metadata->method_or_setter_selector_id = helper_->ReadUInt();
  metadata->getter_selector_id = helper_->ReadUInt();
  return true;
}

ProcedureAttributesMetadata
ProcedureAttributesMetadataHelper::GetProcedureAttributes(
    intptr_t node_offset) {
  ProcedureAttributesMetadata metadata;
  ReadMetadata(node_offset, &metadata);
  return metadata;
}

ObfuscationProhibitionsMetadataHelper::ObfuscationProhibitionsMetadataHelper(
    KernelReaderHelper* helper)
    : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}

void ObfuscationProhibitionsMetadataHelper::ReadMetadata(intptr_t node_offset) {
  intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
  if (md_offset < 0) {
    return;
  }

  AlternativeReadingScopeWithNewData alt(&helper_->reader_,
                                         &H.metadata_payloads(), md_offset);
  Obfuscator O(Thread::Current(), String::Handle());

  intptr_t len = helper_->ReadUInt32();
  for (int i = 0; i < len; ++i) {
    StringIndex name = helper_->ReadStringReference();
    O.PreventRenaming(translation_helper_.DartSymbolPlain(name));
  }
  return;
}

LoadingUnitsMetadataHelper::LoadingUnitsMetadataHelper(
    KernelReaderHelper* helper)
    : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}

void LoadingUnitsMetadataHelper::ReadMetadata(intptr_t node_offset) {
  intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
  if (md_offset < 0) {
    return;
  }

  AlternativeReadingScopeWithNewData alt(&helper_->reader_,
                                         &H.metadata_payloads(), md_offset);

  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  intptr_t unit_count = helper_->ReadUInt();
  Array& loading_units = Array::Handle(zone, Array::New(unit_count + 1));
  LoadingUnit& unit = LoadingUnit::Handle(zone);
  LoadingUnit& parent = LoadingUnit::Handle(zone);
  Library& lib = Library::Handle(zone);

  for (int i = 0; i < unit_count; i++) {
    intptr_t id = helper_->ReadUInt();
    unit = LoadingUnit::New();
    unit.set_id(id);

    intptr_t parent_id = helper_->ReadUInt();
    RELEASE_ASSERT(parent_id < id);
    parent ^= loading_units.At(parent_id);
    RELEASE_ASSERT(parent.IsNull() == (parent_id == 0));
    unit.set_parent(parent);

    intptr_t library_count = helper_->ReadUInt();
    for (intptr_t j = 0; j < library_count; j++) {
      const String& uri =
          translation_helper_.DartSymbolPlain(helper_->ReadStringReference());
      lib = Library::LookupLibrary(thread, uri);
      if (lib.IsNull()) {
        FATAL1("Missing library: %s\n", uri.ToCString());
      }
      lib.set_loading_unit(unit);
    }

    loading_units.SetAt(id, unit);
  }

  ObjectStore* object_store = IG->object_store();
  ASSERT(object_store->loading_units() == Array::null());
  object_store->set_loading_units(loading_units);
}

CallSiteAttributesMetadataHelper::CallSiteAttributesMetadataHelper(
    KernelReaderHelper* helper,
    TypeTranslator* type_translator)
    : MetadataHelper(helper, tag(), /* precompiler_only = */ false),
      type_translator_(*type_translator) {}

bool CallSiteAttributesMetadataHelper::ReadMetadata(
    intptr_t node_offset,
    CallSiteAttributesMetadata* metadata) {
  intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
  if (md_offset < 0) {
    return false;
  }

  AlternativeReadingScopeWithNewData alt(&helper_->reader_,
                                         &H.metadata_payloads(), md_offset);

  metadata->receiver_type = &type_translator_.BuildType();
  return true;
}

CallSiteAttributesMetadata
CallSiteAttributesMetadataHelper::GetCallSiteAttributes(intptr_t node_offset) {
  CallSiteAttributesMetadata metadata;
  ReadMetadata(node_offset, &metadata);
  return metadata;
}

TableSelectorMetadataHelper::TableSelectorMetadataHelper(
    KernelReaderHelper* helper)
    : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}

TableSelectorMetadata* TableSelectorMetadataHelper::GetTableSelectorMetadata(
    Zone* zone) {
  const intptr_t node_offset = GetComponentMetadataPayloadOffset();
  const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
  if (md_offset < 0) {
    return nullptr;
  }

  AlternativeReadingScopeWithNewData alt(&helper_->reader_,
                                         &H.metadata_payloads(), md_offset);

  const intptr_t num_selectors = helper_->ReadUInt();
  TableSelectorMetadata* metadata =
      new (zone) TableSelectorMetadata(num_selectors);
  for (intptr_t i = 0; i < num_selectors; i++) {
    ReadTableSelectorInfo(&metadata->selectors[i]);
  }
  return metadata;
}

void TableSelectorMetadataHelper::ReadTableSelectorInfo(
    TableSelectorInfo* info) {
  info->call_count = helper_->ReadUInt();
  uint8_t flags = helper_->ReadByte();
  info->called_on_null = (flags & kCalledOnNullBit) != 0;
  info->torn_off = (flags & kTornOffBit) != 0;
}

UnboxingInfoMetadataHelper::UnboxingInfoMetadataHelper(
    KernelReaderHelper* helper)
    : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}

UnboxingInfoMetadata* UnboxingInfoMetadataHelper::GetUnboxingInfoMetadata(
    intptr_t node_offset) {
  const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);

  if (md_offset < 0) {
    return nullptr;
  }

  AlternativeReadingScopeWithNewData alt(&helper_->reader_,
                                         &H.metadata_payloads(), md_offset);

  const intptr_t num_args = helper_->ReadUInt();
  const auto info = new (helper_->zone_) UnboxingInfoMetadata();
  info->SetArgsCount(num_args);
  for (intptr_t i = 0; i < num_args; i++) {
    const intptr_t arg_info = helper_->ReadByte();
    assert(arg_info >= UnboxingInfoMetadata::kBoxed &&
           arg_info < UnboxingInfoMetadata::kUnboxingCandidate);
    info->unboxed_args_info[i] =
        static_cast<UnboxingInfoMetadata::UnboxingInfoTag>(arg_info);
  }
  const intptr_t return_info = helper_->ReadByte();
  assert(return_info >= UnboxingInfoMetadata::kBoxed &&
         return_info < UnboxingInfoMetadata::kUnboxingCandidate);
  info->return_info =
      static_cast<UnboxingInfoMetadata::UnboxingInfoTag>(return_info);
  return info;
}

intptr_t KernelReaderHelper::ReaderOffset() const {
  return reader_.offset();
}

intptr_t KernelReaderHelper::ReaderSize() const {
  return reader_.size();
}

void KernelReaderHelper::SetOffset(intptr_t offset) {
  reader_.set_offset(offset);
}

void KernelReaderHelper::SkipBytes(intptr_t bytes) {
  reader_.set_offset(ReaderOffset() + bytes);
}

bool KernelReaderHelper::ReadBool() {
  return reader_.ReadBool();
}

uint8_t KernelReaderHelper::ReadByte() {
  return reader_.ReadByte();
}

uint32_t KernelReaderHelper::ReadUInt() {
  return reader_.ReadUInt();
}

uint32_t KernelReaderHelper::ReadUInt32() {
  return reader_.ReadUInt32();
}

uint32_t KernelReaderHelper::PeekUInt() {
  AlternativeReadingScope alt(&reader_);
  return reader_.ReadUInt();
}

double KernelReaderHelper::ReadDouble() {
  return reader_.ReadDouble();
}

uint32_t KernelReaderHelper::PeekListLength() {
  AlternativeReadingScope alt(&reader_);
  return reader_.ReadListLength();
}

intptr_t KernelReaderHelper::ReadListLength() {
  return reader_.ReadListLength();
}

StringIndex KernelReaderHelper::ReadStringReference() {
  return StringIndex(ReadUInt());
}

NameIndex KernelReaderHelper::ReadCanonicalNameReference() {
  return reader_.ReadCanonicalNameReference();
}

NameIndex KernelReaderHelper::ReadInterfaceMemberNameReference() {
  NameIndex name_index = reader_.ReadCanonicalNameReference();
  NameIndex origin_name_index = reader_.ReadCanonicalNameReference();
  if (!FLAG_precompiled_mode && origin_name_index != NameIndex::kInvalidName) {
    // Reference to a skipped member signature target, return the origin target.
    return origin_name_index;
  }
  return name_index;
}

StringIndex KernelReaderHelper::ReadNameAsStringIndex() {
  StringIndex name_index = ReadStringReference();  // read name index.
  if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
    ReadUInt();  // read library index.
  }
  return name_index;
}

const String& KernelReaderHelper::ReadNameAsMethodName() {
  StringIndex name_index = ReadStringReference();  // read name index.
  if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
    NameIndex library_reference =
        ReadCanonicalNameReference();  // read library index.
    return H.DartMethodName(library_reference, name_index);
  } else {
    return H.DartMethodName(NameIndex(), name_index);
  }
}

const String& KernelReaderHelper::ReadNameAsSetterName() {
  StringIndex name_index = ReadStringReference();  // read name index.
  if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
    NameIndex library_reference =
        ReadCanonicalNameReference();  // read library index.
    return H.DartSetterName(library_reference, name_index);
  } else {
    return H.DartSetterName(NameIndex(), name_index);
  }
}

const String& KernelReaderHelper::ReadNameAsGetterName() {
  StringIndex name_index = ReadStringReference();  // read name index.
  if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
    NameIndex library_reference =
        ReadCanonicalNameReference();  // read library index.
    return H.DartGetterName(library_reference, name_index);
  } else {
    return H.DartGetterName(NameIndex(), name_index);
  }
}

const String& KernelReaderHelper::ReadNameAsFieldName() {
  StringIndex name_index = ReadStringReference();  // read name index.
  if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
    NameIndex library_reference =
        ReadCanonicalNameReference();  // read library index.
    return H.DartFieldName(library_reference, name_index);
  } else {
    return H.DartFieldName(NameIndex(), name_index);
  }
}

void KernelReaderHelper::SkipFlags() {
  ReadFlags();
}

void KernelReaderHelper::SkipStringReference() {
  ReadUInt();
}

void KernelReaderHelper::SkipConstantReference() {
  ReadUInt();
}

void KernelReaderHelper::SkipCanonicalNameReference() {
  ReadUInt();
}

void KernelReaderHelper::SkipInterfaceMemberNameReference() {
  SkipCanonicalNameReference();
  SkipCanonicalNameReference();
}

void KernelReaderHelper::ReportUnexpectedTag(const char* variant, Tag tag) {
  FATAL3("Unexpected tag %d (%s) in ?, expected %s", tag, Reader::TagName(tag),
         variant);
}

void KernelReaderHelper::ReadUntilFunctionNode() {
  const Tag tag = PeekTag();
  if (tag == kProcedure) {
    ProcedureHelper procedure_helper(this);
    procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction);
    // Now at start of FunctionNode.
  } else if (tag == kConstructor) {
    ConstructorHelper constructor_helper(this);
    constructor_helper.ReadUntilExcluding(ConstructorHelper::kFunction);
    // Now at start of FunctionNode.
    // Notice that we also have a list of initializers after that!
  } else if (tag == kFunctionNode) {
    // Already at start of FunctionNode.
  } else {
    ReportUnexpectedTag("a procedure, a constructor or a function node", tag);
    UNREACHABLE();
  }
}

void KernelReaderHelper::SkipDartType() {
  Tag tag = ReadTag();
  switch (tag) {
    case kInvalidType:
    case kDynamicType:
    case kVoidType:
      // those contain nothing.
      return;
    case kNeverType:
      ReadNullability();
      return;
    case kInterfaceType:
      SkipInterfaceType(false);
      return;
    case kSimpleInterfaceType:
      SkipInterfaceType(true);
      return;
    case kFunctionType:
      SkipFunctionType(false);
      return;
    case kSimpleFunctionType:
      SkipFunctionType(true);
      return;
    case kTypedefType:
      ReadNullability();      // read nullability.
      ReadUInt();             // read index for canonical name.
      SkipListOfDartTypes();  // read list of types.
      return;
    case kTypeParameterType:
      ReadNullability();       // read nullability.
      ReadUInt();              // read index for parameter.
      SkipOptionalDartType();  // read bound bound.
      return;
    default:
      ReportUnexpectedTag("type", tag);
      UNREACHABLE();
  }
}

void KernelReaderHelper::SkipOptionalDartType() {
  Tag tag = ReadTag();  // read tag.
  if (tag == kNothing) {
    return;
  }
  ASSERT(tag == kSomething);

  SkipDartType();  // read type.
}

void KernelReaderHelper::SkipInterfaceType(bool simple) {
  ReadNullability();  // read nullability.
  ReadUInt();         // read klass_name.
  if (!simple) {
    SkipListOfDartTypes();  // read list of types.
  }
}

void KernelReaderHelper::SkipFunctionType(bool simple) {
  ReadNullability();  // read nullability.

  if (!simple) {
    SkipTypeParametersList();  // read type_parameters.
    ReadUInt();                // read required parameter count.
    ReadUInt();                // read total parameter count.
  }

  SkipListOfDartTypes();  // read positional_parameters types.

  if (!simple) {
    const intptr_t named_count =
        ReadListLength();  // read named_parameters list length.
    for (intptr_t i = 0; i < named_count; ++i) {
      // read string reference (i.e. named_parameters[i].name).
      SkipStringReference();
      SkipDartType();  // read named_parameters[i].type.
      SkipBytes(1);    // read flags
    }
  }

  SkipDartType();  // read return type.
}

void KernelReaderHelper::SkipStatementList() {
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    SkipStatement();  // read ith expression.
  }
}

void KernelReaderHelper::SkipListOfExpressions() {
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    SkipExpression();  // read ith expression.
  }
}

void KernelReaderHelper::SkipListOfDartTypes() {
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    SkipDartType();  // read ith type.
  }
}

void KernelReaderHelper::SkipListOfStrings() {
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    SkipStringReference();  // read ith string index.
  }
}

void KernelReaderHelper::SkipListOfVariableDeclarations() {
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    SkipVariableDeclaration();  // read ith variable declaration.
  }
}

void KernelReaderHelper::SkipListOfCanonicalNameReferences() {
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    SkipCanonicalNameReference();
  }
}

void KernelReaderHelper::SkipTypeParametersList() {
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    TypeParameterHelper helper(this);
    helper.Finish();
  }
}

void KernelReaderHelper::SkipInitializer() {
  Tag tag = ReadTag();
  ReadByte();  // read isSynthetic flag.
  switch (tag) {
    case kInvalidInitializer:
      return;
    case kFieldInitializer:
      SkipCanonicalNameReference();  // read field_reference.
      SkipExpression();              // read value.
      return;
    case kSuperInitializer:
      ReadPosition();                // read position.
      SkipCanonicalNameReference();  // read target_reference.
      SkipArguments();               // read arguments.
      return;
    case kRedirectingInitializer:
      ReadPosition();                // read position.
      SkipCanonicalNameReference();  // read target_reference.
      SkipArguments();               // read arguments.
      return;
    case kLocalInitializer:
      SkipVariableDeclaration();  // read variable.
      return;
    case kAssertInitializer:
      SkipStatement();
      return;
    default:
      ReportUnexpectedTag("initializer", tag);
      UNREACHABLE();
  }
}

void KernelReaderHelper::SkipExpression() {
  uint8_t payload = 0;
  Tag tag = ReadTag(&payload);
  switch (tag) {
    case kInvalidExpression:
      ReadPosition();
      SkipStringReference();
      if (ReadTag() == kSomething) {
        SkipExpression();  // read expression.
      }
      return;
    case kVariableGet:
      ReadPosition();          // read position.
      ReadUInt();              // read kernel position.
      ReadUInt();              // read relative variable index.
      SkipOptionalDartType();  // read promoted type.
      return;
    case kSpecializedVariableGet:
      ReadPosition();  // read position.
      ReadUInt();      // read kernel position.
      return;
    case kVariableSet:
      ReadPosition();    // read position.
      ReadUInt();        // read kernel position.
      ReadUInt();        // read relative variable index.
      SkipExpression();  // read expression.
      return;
    case kSpecializedVariableSet:
      ReadPosition();    // read position.
      ReadUInt();        // read kernel position.
      SkipExpression();  // read expression.
      return;
    case kInstanceGet:
      ReadByte();                          // read kind.
      ReadPosition();                      // read position.
      SkipExpression();                    // read receiver.
      SkipName();                          // read name.
      SkipDartType();                      // read result_type.
      SkipInterfaceMemberNameReference();  // read interface_target_reference.
      return;
    case kDynamicGet:
      ReadByte();        // read kind.
      ReadPosition();    // read position.
      SkipExpression();  // read receiver.
      SkipName();        // read name.
      return;
    case kInstanceTearOff:
      ReadByte();                          // read kind.
      ReadPosition();                      // read position.
      SkipExpression();                    // read receiver.
      SkipName();                          // read name.
      SkipDartType();                      // read result_type.
      SkipInterfaceMemberNameReference();  // read interface_target_reference.
      return;
    case kFunctionTearOff:
      ReadPosition();    // read position.
      SkipExpression();  // read receiver.
      return;
    case kInstanceSet:
      ReadByte();                          // read kind.
      ReadPosition();                      // read position.
      SkipExpression();                    // read receiver.
      SkipName();                          // read name.
      SkipExpression();                    // read value.
      SkipInterfaceMemberNameReference();  // read interface_target_reference.
      return;
    case kDynamicSet:
      ReadByte();        // read kind.
      ReadPosition();    // read position.
      SkipExpression();  // read receiver.
      SkipName();        // read name.
      SkipExpression();  // read value.
      return;
    case kSuperPropertyGet:
      ReadPosition();                      // read position.
      SkipName();                          // read name.
      SkipInterfaceMemberNameReference();  // read interface_target_reference.
      return;
    case kSuperPropertySet:
      ReadPosition();                      // read position.
      SkipName();                          // read name.
      SkipExpression();                    // read value.
      SkipInterfaceMemberNameReference();  // read interface_target_reference.
      return;
    case kStaticGet:
      ReadPosition();                // read position.
      SkipCanonicalNameReference();  // read target_reference.
      return;
    case kStaticSet:
      ReadPosition();                // read position.
      SkipCanonicalNameReference();  // read target_reference.
      SkipExpression();              // read expression.
      return;
    case kInstanceInvocation:
      ReadByte();                          // read kind.
      ReadFlags();                         // read flags.
      ReadPosition();                      // read position.
      SkipExpression();                    // read receiver.
      SkipName();                          // read name.
      SkipArguments();                     // read arguments.
      SkipDartType();                      // read function_type.
      SkipInterfaceMemberNameReference();  // read interface_target_reference.
      return;
    case kDynamicInvocation:
      ReadByte();        // read kind.
      ReadPosition();    // read position.
      SkipExpression();  // read receiver.
      SkipName();        // read name.
      SkipArguments();   // read arguments.
      return;
    case kLocalFunctionInvocation:
      ReadPosition();   // read position.
      ReadUInt();       // read variable kernel position.
      ReadUInt();       // read relative variable index.
      SkipArguments();  // read arguments.
      SkipDartType();   // read function_type.
      return;
    case kFunctionInvocation:
      ReadByte();        // read kind.
      ReadPosition();    // read position.
      SkipExpression();  // read receiver.
      SkipArguments();   // read arguments.
      SkipDartType();    // read function_type.
      return;
    case kEqualsCall:
      ReadPosition();                      // read position.
      SkipExpression();                    // read left.
      SkipExpression();                    // read right.
      SkipDartType();                      // read function_type.
      SkipInterfaceMemberNameReference();  // read interface_target_reference.
      return;
    case kEqualsNull:
      ReadPosition();    // read position.
      SkipExpression();  // read expression.
      return;
    case kSuperMethodInvocation:
      ReadPosition();                      // read position.
      SkipName();                          // read name.
      SkipArguments();                     // read arguments.
      SkipInterfaceMemberNameReference();  // read interface_target_reference.
      return;
    case kStaticInvocation:
      ReadPosition();                // read position.
      SkipCanonicalNameReference();  // read procedure_reference.
      SkipArguments();               // read arguments.
      return;
    case kConstructorInvocation:
      ReadPosition();                // read position.
      SkipCanonicalNameReference();  // read target_reference.
      SkipArguments();               // read arguments.
      return;
    case kNot:
      SkipExpression();  // read expression.
      return;
    case kNullCheck:
      ReadPosition();    // read position.
      SkipExpression();  // read expression.
      return;
    case kLogicalExpression:
      SkipExpression();  // read left.
      SkipBytes(1);      // read operator.
      SkipExpression();  // read right.
      return;
    case kConditionalExpression:
      SkipExpression();        // read condition.
      SkipExpression();        // read then.
      SkipExpression();        // read otherwise.
      SkipOptionalDartType();  // read unused static type.
      return;
    case kStringConcatenation:
      ReadPosition();           // read position.
      SkipListOfExpressions();  // read list of expressions.
      return;
    case kIsExpression:
      ReadPosition();  // read position.
      if (translation_helper_.info().kernel_binary_version() >= 38) {
        SkipFlags();  // read flags.
      }
      SkipExpression();  // read operand.
      SkipDartType();    // read type.
      return;
    case kAsExpression:
      ReadPosition();    // read position.
      SkipFlags();       // read flags.
      SkipExpression();  // read operand.
      SkipDartType();    // read type.
      return;
    case kTypeLiteral:
      SkipDartType();  // read type.
      return;
    case kThisExpression:
      return;
    case kRethrow:
      ReadPosition();  // read position.
      return;
    case kThrow:
      ReadPosition();    // read position.
      SkipExpression();  // read expression.
      return;
    case kListLiteral:
      ReadPosition();           // read position.
      SkipDartType();           // read type.
      SkipListOfExpressions();  // read list of expressions.
      return;
    case kSetLiteral:
      // Set literals are currently desugared in the frontend and will not
      // reach the VM. See http://dartbug.com/35124 for discussion.
      UNREACHABLE();
      return;
    case kMapLiteral: {
      ReadPosition();                           // read position.
      SkipDartType();                           // read key type.
      SkipDartType();                           // read value type.
      intptr_t list_length = ReadListLength();  // read list length.
      for (intptr_t i = 0; i < list_length; ++i) {
        SkipExpression();  // read ith key.
        SkipExpression();  // read ith value.
      }
      return;
    }
    case kFunctionExpression:
      ReadPosition();      // read position.
      SkipFunctionNode();  // read function node.
      return;
    case kLet:
      ReadPosition();             // read position.
      SkipVariableDeclaration();  // read variable declaration.
      SkipExpression();           // read expression.
      return;
    case kBlockExpression:
      SkipStatementList();
      SkipExpression();  // read expression.
      return;
    case kInstantiation:
      SkipExpression();       // read expression.
      SkipListOfDartTypes();  // read type arguments.
      return;
    case kBigIntLiteral:
      SkipStringReference();  // read string reference.
      return;
    case kStringLiteral:
      SkipStringReference();  // read string reference.
      return;
    case kSpecializedIntLiteral:
      return;
    case kNegativeIntLiteral:
      ReadUInt();  // read value.
      return;
    case kPositiveIntLiteral:
      ReadUInt();  // read value.
      return;
    case kDoubleLiteral:
      ReadDouble();  // read value.
      return;
    case kTrueLiteral:
      return;
    case kFalseLiteral:
      return;
    case kNullLiteral:
      return;
    case kConstantExpression:
      ReadPosition();  // read position.
      SkipDartType();  // read type.
      SkipConstantReference();
      return;
    case kLoadLibrary:
    case kCheckLibraryIsLoaded:
      ReadUInt();  // skip library index
      return;
    case kAwaitExpression:
      ReadPosition();    // read position.
      SkipExpression();  // read operand.
      return;
    case kConstStaticInvocation:
    case kConstConstructorInvocation:
    case kConstListLiteral:
    case kConstSetLiteral:
    case kConstMapLiteral:
    case kSymbolLiteral:
    case kListConcatenation:
    case kSetConcatenation:
    case kMapConcatenation:
    case kInstanceCreation:
    case kFileUriExpression:
    case kStaticTearOff:
      // These nodes are internal to the front end and
      // removed by the constant evaluator.
    default:
      ReportUnexpectedTag("expression", tag);
      UNREACHABLE();
  }
}

void KernelReaderHelper::SkipStatement() {
  Tag tag = ReadTag();  // read tag.
  switch (tag) {
    case kExpressionStatement:
      SkipExpression();  // read expression.
      return;
    case kBlock:
      ReadPosition();  // read file offset.
      ReadPosition();  // read file end offset.
      SkipStatementList();
      return;
    case kEmptyStatement:
      return;
    case kAssertBlock:
      SkipStatementList();
      return;
    case kAssertStatement:
      SkipExpression();  // Read condition.
      ReadPosition();    // read condition start offset.
      ReadPosition();    // read condition end offset.
      if (ReadTag() == kSomething) {
        SkipExpression();  // read (rest of) message.
      }
      return;
    case kLabeledStatement:
      SkipStatement();  // read body.
      return;
    case kBreakStatement:
      ReadPosition();  // read position.
      ReadUInt();      // read target_index.
      return;
    case kWhileStatement:
      ReadPosition();    // read position.
      SkipExpression();  // read condition.
      SkipStatement();   // read body.
      return;
    case kDoStatement:
      ReadPosition();    // read position.
      SkipStatement();   // read body.
      SkipExpression();  // read condition.
      return;
    case kForStatement: {
      ReadPosition();                    // read position.
      SkipListOfVariableDeclarations();  // read variables.
      Tag tag = ReadTag();               // Read first part of condition.
      if (tag == kSomething) {
        SkipExpression();  // read rest of condition.
      }
      SkipListOfExpressions();  // read updates.
      SkipStatement();          // read body.
      return;
    }
    case kForInStatement:
    case kAsyncForInStatement:
      ReadPosition();             // read position.
      ReadPosition();             // read body position.
      SkipVariableDeclaration();  // read variable.
      SkipExpression();           // read iterable.
      SkipStatement();            // read body.
      return;
    case kSwitchStatement: {
      ReadPosition();                     // read position.
      SkipExpression();                   // read condition.
      int case_count = ReadListLength();  // read number of cases.
      for (intptr_t i = 0; i < case_count; ++i) {
        int expression_count = ReadListLength();  // read number of expressions.
        for (intptr_t j = 0; j < expression_count; ++j) {
          ReadPosition();    // read jth position.
          SkipExpression();  // read jth expression.
        }
        ReadBool();       // read is_default.
        SkipStatement();  // read body.
      }
      return;
    }
    case kContinueSwitchStatement:
      ReadPosition();  // read position.
      ReadUInt();      // read target_index.
      return;
    case kIfStatement:
      ReadPosition();    // read position.
      SkipExpression();  // read condition.
      SkipStatement();   // read then.
      SkipStatement();   // read otherwise.
      return;
    case kReturnStatement: {
      ReadPosition();       // read position
      Tag tag = ReadTag();  // read (first part of) expression.
      if (tag == kSomething) {
        SkipExpression();  // read (rest of) expression.
      }
      return;
    }
    case kTryCatch: {
      SkipStatement();                          // read body.
      ReadByte();                               // read flags
      intptr_t catch_count = ReadListLength();  // read number of catches.
      for (intptr_t i = 0; i < catch_count; ++i) {
        ReadPosition();   // read position.
        SkipDartType();   // read guard.
        tag = ReadTag();  // read first part of exception.
        if (tag == kSomething) {
          SkipVariableDeclaration();  // read exception.
        }
        tag = ReadTag();  // read first part of stack trace.
        if (tag == kSomething) {
          SkipVariableDeclaration();  // read stack trace.
        }
        SkipStatement();  // read body.
      }
      return;
    }
    case kTryFinally:
      SkipStatement();  // read body.
      SkipStatement();  // read finalizer.
      return;
    case kYieldStatement: {
      ReadPosition();    // read position.
      ReadByte();        // read flags.
      SkipExpression();  // read expression.
      return;
    }
    case kVariableDeclaration:
      SkipVariableDeclaration();  // read variable declaration.
      return;
    case kFunctionDeclaration:
      ReadPosition();             // read position.
      SkipVariableDeclaration();  // read variable.
      SkipFunctionNode();         // read function node.
      return;
    default:
      ReportUnexpectedTag("statement", tag);
      UNREACHABLE();
  }
}

void KernelReaderHelper::SkipFunctionNode() {
  FunctionNodeHelper function_node_helper(this);
  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
}

void KernelReaderHelper::SkipName() {
  StringIndex name_index = ReadStringReference();  // read name index.
  if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
    SkipCanonicalNameReference();  // read library index.
  }
}

void KernelReaderHelper::SkipArguments() {
  ReadUInt();  // read argument count.

  SkipListOfDartTypes();    // read list of types.
  SkipListOfExpressions();  // read positionals.

  // List of named.
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    SkipStringReference();  // read ith name index.
    SkipExpression();       // read ith expression.
  }
}

void KernelReaderHelper::SkipVariableDeclaration() {
  VariableDeclarationHelper helper(this);
  helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);
}

void KernelReaderHelper::SkipLibraryCombinator() {
  ReadBool();                        // read is_show.
  intptr_t name_count = ReadUInt();  // read list length.
  for (intptr_t j = 0; j < name_count; ++j) {
    ReadUInt();  // read ith entry of name_indices.
  }
}

void KernelReaderHelper::SkipLibraryDependency() {
  ReadPosition();  // read file offset.
  ReadFlags();
  SkipListOfExpressions();  // Annotations.
  ReadCanonicalNameReference();
  ReadStringReference();  // Name.
  intptr_t combinator_count = ReadListLength();
  for (intptr_t i = 0; i < combinator_count; ++i) {
    SkipLibraryCombinator();
  }
}

void KernelReaderHelper::SkipLibraryPart() {
  SkipListOfExpressions();  // Read annotations.
  SkipStringReference();    // Read part URI index.
}

TokenPosition KernelReaderHelper::ReadPosition() {
  TokenPosition position = reader_.ReadPosition();
  RecordTokenPosition(position);
  return position;
}

intptr_t KernelReaderHelper::SourceTableSize() {
  AlternativeReadingScope alt(&reader_);
  intptr_t library_count = reader_.ReadFromIndexNoReset(
      reader_.size(), LibraryCountFieldCountFromEnd, 1, 0);

  const intptr_t count_from_first_library_offset =
      SourceTableFieldCountFromFirstLibraryOffset;

  intptr_t source_table_offset = reader_.ReadFromIndexNoReset(
      reader_.size(),
      LibraryCountFieldCountFromEnd + 1 + library_count + 1 +
          count_from_first_library_offset,
      1, 0);
  SetOffset(source_table_offset);  // read source table offset.
  return reader_.ReadUInt32();     // read source table size.
}

intptr_t KernelReaderHelper::GetOffsetForSourceInfo(intptr_t index) {
  AlternativeReadingScope alt(&reader_);
  intptr_t library_count = reader_.ReadFromIndexNoReset(
      reader_.size(), LibraryCountFieldCountFromEnd, 1, 0);

  const intptr_t count_from_first_library_offset =
      SourceTableFieldCountFromFirstLibraryOffset;

  intptr_t source_table_offset = reader_.ReadFromIndexNoReset(
      reader_.size(),
      LibraryCountFieldCountFromEnd + 1 + library_count + 1 +
          count_from_first_library_offset,
      1, 0);
  intptr_t next_field_offset = reader_.ReadUInt32();
  SetOffset(source_table_offset);
  intptr_t size = reader_.ReadUInt32();  // read source table size.

  return reader_.ReadFromIndexNoReset(next_field_offset, 0, size, index);
}

String& KernelReaderHelper::SourceTableUriFor(intptr_t index) {
  AlternativeReadingScope alt(&reader_);
  SetOffset(GetOffsetForSourceInfo(index));
  intptr_t size = ReadUInt();  // read uri List<byte> size.
  return H.DartString(reader_.BufferAt(ReaderOffset()), size, Heap::kOld);
}

const String& KernelReaderHelper::GetSourceFor(intptr_t index) {
  AlternativeReadingScope alt(&reader_);
  SetOffset(GetOffsetForSourceInfo(index));
  SkipBytes(ReadUInt());       // skip uri.
  intptr_t size = ReadUInt();  // read source List<byte> size.
  ASSERT(size >= 0);
  if (size == 0) {
    return Symbols::Empty();
  } else {
    return H.DartString(reader_.BufferAt(ReaderOffset()), size, Heap::kOld);
  }
}

TypedDataPtr KernelReaderHelper::GetLineStartsFor(intptr_t index) {
  // Line starts are delta encoded. So get the max delta first so that we
  // can store them as tighly as possible.
  AlternativeReadingScope alt(&reader_);
  SetOffset(GetOffsetForSourceInfo(index));
  SkipBytes(ReadUInt());  // skip uri.
  SkipBytes(ReadUInt());  // skip source.
  const intptr_t line_start_count = ReadUInt();
  return reader_.ReadLineStartsData(line_start_count);
}

String& KernelReaderHelper::SourceTableImportUriFor(intptr_t index,
                                                    uint32_t binaryVersion) {
  if (binaryVersion < 22) {
    return SourceTableUriFor(index);
  }

  AlternativeReadingScope alt(&reader_);
  SetOffset(GetOffsetForSourceInfo(index));
  SkipBytes(ReadUInt());                         // skip uri.
  SkipBytes(ReadUInt());                         // skip source.
  const intptr_t line_start_count = ReadUInt();  // read number of line start
                                                 // entries.
  for (intptr_t i = 0; i < line_start_count; ++i) {
    ReadUInt();
  }

  intptr_t size = ReadUInt();  // read import uri List<byte> size.
  return H.DartString(reader_.BufferAt(ReaderOffset()), size, Heap::kOld);
}

ExternalTypedDataPtr KernelReaderHelper::GetConstantCoverageFor(
    intptr_t index) {
  AlternativeReadingScope alt(&reader_);
  SetOffset(GetOffsetForSourceInfo(index));
  SkipBytes(ReadUInt());                         // skip uri.
  SkipBytes(ReadUInt());                         // skip source.
  const intptr_t line_start_count = ReadUInt();  // read number of line start
                                                 // entries.
  for (intptr_t i = 0; i < line_start_count; ++i) {
    ReadUInt();
  }

  SkipBytes(ReadUInt());  // skip import uri.

  intptr_t start_offset = ReaderOffset();

  // Read past "constant coverage constructors".
  const intptr_t constant_coverage_constructors = ReadUInt();
  for (intptr_t i = 0; i < constant_coverage_constructors; ++i) {
    ReadUInt();
  }

  intptr_t end_offset = ReaderOffset();

  return reader_.ExternalDataFromTo(start_offset, end_offset);
}

intptr_t ActiveClass::MemberTypeParameterCount(Zone* zone) {
  ASSERT(member != NULL);
  if (member->IsFactory()) {
    return klass->NumTypeParameters();
  } else if (member->IsMethodExtractor()) {
    Function& extracted =
        Function::Handle(zone, member->extracted_method_closure());
    return extracted.NumTypeParameters();
  } else {
    return member->NumTypeParameters();
  }
}

ActiveTypeParametersScope::ActiveTypeParametersScope(
    ActiveClass* active_class,
    const Function& innermost,
    const FunctionType* innermost_signature,
    Zone* Z)
    : active_class_(active_class), saved_(*active_class), zone_(Z) {
  active_class_->enclosing = innermost_signature;

  intptr_t num_params = 0;

  Function& f = Function::Handle(Z);
  for (f = innermost.ptr(); f.parent_function() != Object::null();
       f = f.parent_function()) {
    num_params += f.NumTypeParameters();
  }
  if (num_params == 0) return;

  TypeArguments& params =
      TypeArguments::Handle(Z, TypeArguments::New(num_params));

  intptr_t index = num_params;
  for (f = innermost.ptr(); f.parent_function() != Object::null();
       f = f.parent_function()) {
    for (intptr_t j = f.NumTypeParameters() - 1; j >= 0; --j) {
      const auto& type_param = TypeParameter::Handle(Z, f.TypeParameterAt(j));
      params.SetTypeAt(--index, type_param);
      active_class_->RecordDerivedTypeParameter(Z, type_param);
    }
  }

  active_class_->local_type_parameters = &params;
}

ActiveTypeParametersScope::ActiveTypeParametersScope(
    ActiveClass* active_class,
    const FunctionType* innermost_signature,
    Zone* Z)
    : active_class_(active_class), saved_(*active_class), zone_(Z) {
  active_class_->enclosing = innermost_signature;

  const intptr_t num_new_params =
      innermost_signature == nullptr ? active_class->klass->NumTypeParameters()
                                     : innermost_signature->NumTypeParameters();
  if (num_new_params == 0) return;

  const TypeArguments* old_params = active_class->local_type_parameters;
  const intptr_t old_param_count =
      old_params == NULL ? 0 : old_params->Length();
  const TypeArguments& extended_params = TypeArguments::Handle(
      Z, TypeArguments::New(old_param_count + num_new_params));

  intptr_t index = 0;
  for (intptr_t i = 0; i < old_param_count; ++i) {
    extended_params.SetTypeAt(index++,
                              AbstractType::Handle(Z, old_params->TypeAt(i)));
  }
  for (intptr_t i = 0; i < num_new_params; ++i) {
    const auto& type_param =
        TypeParameter::Handle(Z, innermost_signature == nullptr
                                     ? active_class->klass->TypeParameterAt(i)
                                     : innermost_signature->TypeParameterAt(i));
    extended_params.SetTypeAt(index++, type_param);
    active_class->RecordDerivedTypeParameter(Z, type_param);
  }

  active_class_->local_type_parameters = &extended_params;
}

ActiveTypeParametersScope::~ActiveTypeParametersScope() {
  GrowableObjectArray* dropped = active_class_->derived_type_parameters;
  const bool preserve_unpatched =
      dropped != nullptr && saved_.derived_type_parameters == nullptr;
  *active_class_ = saved_;
  if (preserve_unpatched) {
    // Preserve still unpatched derived type parameters that would be dropped.
    auto& derived = TypeParameter::Handle(Z);
    for (intptr_t i = 0, n = dropped->Length(); i < n; ++i) {
      derived ^= dropped->At(i);
      if (derived.bound() == AbstractType::null()) {
        active_class_->RecordDerivedTypeParameter(Z, derived);
      }
    }
  }
}

TypeTranslator::TypeTranslator(KernelReaderHelper* helper,
                               ConstantReader* constant_reader,
                               ActiveClass* active_class,
                               bool finalize,
                               bool apply_canonical_type_erasure,
                               bool in_constant_context)
    : helper_(helper),
      constant_reader_(constant_reader),
      translation_helper_(helper->translation_helper_),
      active_class_(active_class),
      type_parameter_scope_(NULL),
      inferred_type_metadata_helper_(helper_, constant_reader_),
      unboxing_info_metadata_helper_(helper_),
      zone_(translation_helper_.zone()),
      result_(AbstractType::Handle(translation_helper_.zone())),
      finalize_(finalize),
      refers_to_derived_type_param_(false),
      apply_canonical_type_erasure_(apply_canonical_type_erasure),
      in_constant_context_(in_constant_context) {}

AbstractType& TypeTranslator::BuildType() {
  BuildTypeInternal();

  // We return a new `ZoneHandle` here on purpose: The intermediate language
  // instructions do not make a copy of the handle, so we do it.
  return AbstractType::ZoneHandle(Z, result_.ptr());
}

AbstractType& TypeTranslator::BuildTypeWithoutFinalization() {
  bool saved_finalize = finalize_;
  finalize_ = false;
  BuildTypeInternal();
  finalize_ = saved_finalize;

  // We return a new `ZoneHandle` here on purpose: The intermediate language
  // instructions do not make a copy of the handle, so we do it.
  return AbstractType::ZoneHandle(Z, result_.ptr());
}

void TypeTranslator::BuildTypeInternal() {
  Tag tag = helper_->ReadTag();
  switch (tag) {
    case kInvalidType:
    case kDynamicType:
      result_ = Object::dynamic_type().ptr();
      break;
    case kVoidType:
      result_ = Object::void_type().ptr();
      break;
    case kNeverType: {
      Nullability nullability = helper_->ReadNullability();
      if (apply_canonical_type_erasure_ &&
          nullability != Nullability::kNullable) {
        nullability = Nullability::kLegacy;
      }
      result_ = Type::Handle(Z, IG->object_store()->never_type())
                    .ToNullability(nullability, Heap::kOld);
      break;
    }
    case kInterfaceType:
      BuildInterfaceType(false);
      break;
    case kSimpleInterfaceType:
      BuildInterfaceType(true);
      break;
    case kFunctionType:
      BuildFunctionType(false);
      break;
    case kSimpleFunctionType:
      BuildFunctionType(true);
      break;
    case kTypeParameterType:
      BuildTypeParameterType();
      if (result_.IsTypeParameter() &&
          TypeParameter::Cast(result_).bound() == AbstractType::null()) {
        refers_to_derived_type_param_ = true;
      }
      break;
    default:
      helper_->ReportUnexpectedTag("type", tag);
      UNREACHABLE();
  }
}

void TypeTranslator::BuildInterfaceType(bool simple) {
  // NOTE: That an interface type like `T<A, B>` is considered to be
  // malformed iff `T` is malformed.
  //   => We therefore ignore errors in `A` or `B`.

  Nullability nullability = helper_->ReadNullability();
  if (apply_canonical_type_erasure_ && nullability != Nullability::kNullable) {
    nullability = Nullability::kLegacy;
  }

  NameIndex klass_name =
      helper_->ReadCanonicalNameReference();  // read klass_name.

  const Class& klass = Class::Handle(Z, H.LookupClassByKernelClass(klass_name));
  ASSERT(!klass.IsNull());
  if (simple) {
    if (finalize_ || klass.is_type_finalized()) {
      // Fast path for non-generic types: retrieve or populate the class's only
      // canonical type (as long as only one nullability variant is used), which
      // is its declaration type.
      result_ = klass.DeclarationType();
      result_ = Type::Cast(result_).ToNullability(nullability, Heap::kOld);
    } else {
      // Note that the type argument vector is not yet extended.
      result_ = Type::New(klass, Object::null_type_arguments(), nullability);
    }
    return;
  }

  intptr_t length =
      helper_->ReadListLength();  // read type_arguments list length.
  const TypeArguments& type_arguments =
      BuildTypeArguments(length);  // read type arguments.
  result_ = Type::New(klass, type_arguments, nullability);
  result_ = result_.NormalizeFutureOrType(Heap::kOld);
  if (finalize_) {
    result_ = ClassFinalizer::FinalizeType(result_);
  }
}

void TypeTranslator::BuildFunctionType(bool simple) {
  const intptr_t num_enclosing_type_arguments =
      active_class_->enclosing != NULL
          ? active_class_->enclosing->NumTypeArguments()
          : 0;
  Nullability nullability = helper_->ReadNullability();
  if (apply_canonical_type_erasure_ && nullability != Nullability::kNullable) {
    nullability = Nullability::kLegacy;
  }
  FunctionType& signature = FunctionType::ZoneHandle(
      Z, FunctionType::New(num_enclosing_type_arguments, nullability));

  // Suspend finalization of types inside this one. They will be finalized after
  // the whole function type is constructed.
  bool finalize = finalize_;
  finalize_ = false;
  intptr_t type_parameter_count = 0;

  if (!simple) {
    type_parameter_count = helper_->ReadListLength();
    LoadAndSetupTypeParameters(active_class_, Object::null_function(),
                               Object::null_class(), signature,
                               type_parameter_count);
  }

  ActiveTypeParametersScope scope(active_class_, &signature, Z);

  if (!simple) {
    LoadAndSetupBounds(active_class_, Object::null_function(),
                       Object::null_class(), signature, type_parameter_count);
  }

  intptr_t required_count;
  intptr_t all_count;
  intptr_t positional_count;
  if (!simple) {
    required_count = helper_->ReadUInt();  // read required parameter count.
    all_count = helper_->ReadUInt();       // read total parameter count.
    positional_count =
        helper_->ReadListLength();  // read positional_parameters list length.
  } else {
    positional_count =
        helper_->ReadListLength();  // read positional_parameters list length.
    required_count = positional_count;
    all_count = positional_count;
  }

  // The additional first parameter is the receiver (type set to dynamic).
  const intptr_t kImplicitClosureParam = 1;
  signature.set_num_implicit_parameters(kImplicitClosureParam);
  signature.set_num_fixed_parameters(kImplicitClosureParam + required_count);
  signature.SetNumOptionalParameters(all_count - required_count,
                                     positional_count > required_count);

  signature.set_parameter_types(Array::Handle(
      Z, Array::New(kImplicitClosureParam + all_count, Heap::kOld)));
  signature.CreateNameArrayIncludingFlags();

  intptr_t pos = 0;
  signature.SetParameterTypeAt(pos, AbstractType::dynamic_type());
  ++pos;
  for (intptr_t i = 0; i < positional_count; ++i, ++pos) {
    BuildTypeInternal();  // read ith positional parameter.
    signature.SetParameterTypeAt(pos, result_);
  }

  if (!simple) {
    const intptr_t named_count =
        helper_->ReadListLength();  // read named_parameters list length.
    for (intptr_t i = 0; i < named_count; ++i, ++pos) {
      // read string reference (i.e. named_parameters[i].name).
      String& name = H.DartSymbolObfuscate(helper_->ReadStringReference());
      BuildTypeInternal();  // read named_parameters[i].type.
      const uint8_t flags = helper_->ReadFlags();  // read flags
      signature.SetParameterTypeAt(pos, result_);
      signature.SetParameterNameAt(pos, name);
      if ((flags & static_cast<uint8_t>(NamedTypeFlags::kIsRequired)) != 0) {
        signature.SetIsRequiredAt(pos);
      }
    }
  }
  signature.FinalizeNameArray();

  BuildTypeInternal();  // read return type.
  signature.set_result_type(result_);

  finalize_ = finalize;

  if (finalize_) {
    signature ^= ClassFinalizer::FinalizeType(signature);
  }

  result_ = signature.ptr();
}

void TypeTranslator::BuildTypeParameterType() {
  Nullability nullability = helper_->ReadNullability();
  if (apply_canonical_type_erasure_ && nullability != Nullability::kNullable) {
    nullability = Nullability::kLegacy;
  }

  intptr_t parameter_index = helper_->ReadUInt();  // read parameter index.
  helper_->SkipOptionalDartType();                 // read bound.

  // If the type is from a constant, the parameter index isn't offset by the
  // enclosing context.
  if (!in_constant_context_) {
    const intptr_t class_type_parameter_count =
        active_class_->klass->NumTypeParameters();
    if (class_type_parameter_count > parameter_index) {
      result_ =
          active_class_->klass->TypeParameterAt(parameter_index, nullability);
      active_class_->RecordDerivedTypeParameter(Z,
                                                TypeParameter::Cast(result_));
      return;
    }
    parameter_index -= class_type_parameter_count;

    if (active_class_->HasMember()) {
      if (active_class_->MemberIsFactoryProcedure()) {
        //
        // WARNING: This is a little hackish:
        //
        // We have a static factory constructor. The kernel IR gives the factory
        // constructor function its own type parameters (which are equal in name
        // and number to the ones of the enclosing class). I.e.,
        //
        //   class A<T> {
        //     factory A.x() { return new B<T>(); }
        //   }
        //
        //  is basically translated to this:
        //
        //   class A<T> {
        //     static A.x<T'>() { return new B<T'>(); }
        //   }
        //
        if (class_type_parameter_count > parameter_index) {
          result_ = active_class_->klass->TypeParameterAt(parameter_index,
                                                          nullability);
          active_class_->RecordDerivedTypeParameter(
              Z, TypeParameter::Cast(result_));
          return;
        }
        parameter_index -= class_type_parameter_count;
      }
      // Factory function should not be considered as procedure.
      const intptr_t procedure_type_parameter_count =
          (active_class_->MemberIsProcedure() &&
           !active_class_->MemberIsFactoryProcedure())
              ? active_class_->MemberTypeParameterCount(Z)
              : 0;
      if (procedure_type_parameter_count > 0) {
        if (procedure_type_parameter_count > parameter_index) {
          result_ = active_class_->member->TypeParameterAt(parameter_index,
                                                           nullability);
          if (finalize_) {
            ASSERT(TypeParameter::Cast(result_).bound() !=
                   AbstractType::null());
            result_ = ClassFinalizer::FinalizeType(result_);
          } else {
            active_class_->RecordDerivedTypeParameter(
                Z, TypeParameter::Cast(result_));
          }
          return;
        }
        parameter_index -= procedure_type_parameter_count;
      }
    }
  }
  if (active_class_->local_type_parameters != NULL) {
    if (parameter_index < active_class_->local_type_parameters->Length()) {
      const auto& type_param = TypeParameter::CheckedHandle(
          Z, active_class_->local_type_parameters->TypeAt(parameter_index));
      result_ = type_param.ToNullability(nullability, Heap::kOld);
      if (finalize_) {
        ASSERT(TypeParameter::Cast(result_).bound() != AbstractType::null());
        result_ = ClassFinalizer::FinalizeType(result_);
      } else {
        active_class_->RecordDerivedTypeParameter(Z,
                                                  TypeParameter::Cast(result_));
      }
      return;
    }
    parameter_index -= active_class_->local_type_parameters->Length();
  }

  if (type_parameter_scope_ != NULL &&
      parameter_index < type_parameter_scope_->outer_parameter_count() +
                            type_parameter_scope_->parameter_count()) {
    result_ = Type::DynamicType();
    return;
  }

  H.ReportError(
      helper_->script(), TokenPosition::kNoSource,
      "Unbound type parameter found in %s.  Please report this at dartbug.com.",
      active_class_->ToCString());
}

const TypeArguments& TypeTranslator::BuildTypeArguments(intptr_t length) {
  bool only_dynamic = true;
  intptr_t offset = helper_->ReaderOffset();
  for (intptr_t i = 0; i < length; ++i) {
    if (helper_->ReadTag() != kDynamicType) {  // Read the ith types tag.
      only_dynamic = false;
      helper_->SetOffset(offset);
      break;
    }
  }
  TypeArguments& type_arguments = TypeArguments::ZoneHandle(Z);
  if (!only_dynamic) {
    type_arguments = TypeArguments::New(length);
    for (intptr_t i = 0; i < length; ++i) {
      BuildTypeInternal();  // read ith type.
      type_arguments.SetTypeAt(i, result_);
    }

    if (finalize_) {
      type_arguments = type_arguments.Canonicalize(Thread::Current(), nullptr);
    }
  }
  return type_arguments;
}

const TypeArguments& TypeTranslator::BuildInstantiatedTypeArguments(
    const Class& receiver_class,
    intptr_t length) {
  const TypeArguments& type_arguments = BuildTypeArguments(length);

  // If type_arguments is null all arguments are dynamic.
  // If, however, this class doesn't specify all the type arguments directly we
  // still need to finalize the type below in order to get any non-dynamic types
  // from any super. See http://www.dartbug.com/29537.
  if (type_arguments.IsNull() && receiver_class.NumTypeArguments() == length) {
    return type_arguments;
  }

  // We make a temporary [Type] object and use `ClassFinalizer::FinalizeType` to
  // finalize the argument types.
  // (This can for example make the [type_arguments] vector larger)
  Type& type = Type::Handle(Z, Type::New(receiver_class, type_arguments));
  if (finalize_) {
    type ^= ClassFinalizer::FinalizeType(type);
  }

  const TypeArguments& instantiated_type_arguments =
      TypeArguments::ZoneHandle(Z, type.arguments());
  return instantiated_type_arguments;
}

void TypeTranslator::LoadAndSetupTypeParameters(
    ActiveClass* active_class,
    const Function& function,
    const Class& parameterized_class,
    const FunctionType& parameterized_signature,
    intptr_t type_parameter_count) {
  ASSERT(parameterized_class.IsNull() != parameterized_signature.IsNull());
  ASSERT(type_parameter_count >= 0);
  if (type_parameter_count == 0) {
    ASSERT(parameterized_class.IsNull() ||
           parameterized_class.type_parameters() == TypeParameters::null());
    ASSERT(parameterized_signature.IsNull() ||
           parameterized_signature.type_parameters() == TypeParameters::null());
    return;
  }

  // The finalized index of a type parameter can only be determined if the
  // length of the flattened type argument vector is known, which in turn can
  // only be determined after the super type and its class have been loaded.
  // Due to the added complexity of loading classes out of order from the kernel
  // file, class type parameter indices are not finalized during class loading.
  // However, function type parameter indices can be immediately finalized.

  // First setup the type parameters, so if any of the following code uses it
  // (in a recursive way) we're fine.

  // - Create a [ TypeParameters ] object.
  const TypeParameters& type_parameters =
      TypeParameters::Handle(Z, TypeParameters::New(type_parameter_count));
  const Type& null_bound = Type::Handle(Z);

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

  const Library& lib = Library::Handle(Z, active_class->klass->library());
  {
    AlternativeReadingScope alt(&helper_->reader_);
    for (intptr_t i = 0; i < type_parameter_count; i++) {
      TypeParameterHelper helper(helper_);
      helper.Finish();
      type_parameters.SetNameAt(i, H.DartIdentifier(lib, helper.name_index_));
      type_parameters.SetIsGenericCovariantImplAt(
          i, helper.IsGenericCovariantImpl());
      // Bounds are filled later in LoadAndSetupBounds as bound types may
      // reference type parameters which are not created yet.
      type_parameters.SetBoundAt(i, null_bound);
    }
  }
}

void TypeTranslator::LoadAndSetupBounds(
    ActiveClass* active_class,
    const Function& function,
    const Class& parameterized_class,
    const FunctionType& parameterized_signature,
    intptr_t type_parameter_count) {
  ASSERT(parameterized_class.IsNull() != parameterized_signature.IsNull());
  ASSERT(type_parameter_count >= 0);
  if (type_parameter_count == 0) {
    return;
  }

  const TypeParameters& type_parameters = TypeParameters::Handle(
      Z, !parameterized_class.IsNull()
             ? parameterized_class.type_parameters()
             : parameterized_signature.type_parameters());

  // Fill in the bounds and default arguments of all [TypeParameter]s.
  for (intptr_t i = 0; i < type_parameter_count; i++) {
    TypeParameterHelper helper(helper_);
    helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound);

    bool saved_refers_to_derived_type_param = refers_to_derived_type_param_;
    refers_to_derived_type_param_ = false;
    AbstractType& bound = BuildTypeWithoutFinalization();  // read ith bound.
    ASSERT(!bound.IsNull());
    if (refers_to_derived_type_param_) {
      bound = TypeRef::New(bound);
    }
    refers_to_derived_type_param_ = saved_refers_to_derived_type_param;
    type_parameters.SetBoundAt(i, bound);
    helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kDefaultType);
    AbstractType& default_arg = BuildTypeWithoutFinalization();
    ASSERT(!default_arg.IsNull());
    type_parameters.SetDefaultAt(i, default_arg);
    helper.Finish();
  }

  // Fix bounds in all derived type parameters.
  const intptr_t offset = !parameterized_signature.IsNull()
                              ? parameterized_signature.NumParentTypeArguments()
                              : 0;
  if (active_class->derived_type_parameters != nullptr) {
    auto& derived = TypeParameter::Handle(Z);
    auto& bound = AbstractType::Handle(Z);
    for (intptr_t i = 0, n = active_class->derived_type_parameters->Length();
         i < n; ++i) {
      derived ^= active_class->derived_type_parameters->At(i);
      if (derived.bound() == AbstractType::null() &&
          ((!parameterized_class.IsNull() &&
            derived.parameterized_class_id() == parameterized_class.id()) ||
           (!parameterized_signature.IsNull() &&
            derived.parameterized_class_id() == kFunctionCid &&
            derived.index() >= offset &&
            derived.index() < offset + type_parameter_count))) {
        bound = type_parameters.BoundAt(derived.index() - offset);
        ASSERT(!bound.IsNull());
        derived.set_bound(bound);
      }
    }
  }
}

const Type& TypeTranslator::ReceiverType(const Class& klass) {
  ASSERT(!klass.IsNull());
  // Forward expression evaluation class to a real class when
  // creating types.
  if (translation_helper_.GetExpressionEvaluationClass().ptr() == klass.ptr()) {
    ASSERT(translation_helper_.GetExpressionEvaluationRealClass().ptr() !=
           klass.ptr());
    return ReceiverType(translation_helper_.GetExpressionEvaluationRealClass());
  }
  ASSERT(klass.id() != kIllegalCid);
  // Note that if klass is _Closure, the returned type will be _Closure,
  // and not the signature type.
  Type& type = Type::ZoneHandle(Z);
  if (finalize_ || klass.is_type_finalized()) {
    type = klass.DeclarationType();
  } else {
    TypeArguments& type_args = TypeArguments::Handle(Z);
    const intptr_t num_type_params = klass.NumTypeParameters();
    if (num_type_params > 0) {
      type_args = TypeArguments::New(num_type_params);
      TypeParameter& type_param = TypeParameter::Handle();
      for (intptr_t i = 0; i < num_type_params; i++) {
        type_param = klass.TypeParameterAt(i);
        ASSERT(type_param.bound() != AbstractType::null());
        type_args.SetTypeAt(i, type_param);
      }
    }
    type = Type::New(klass, type_args, Nullability::kNonNullable);
  }
  return type;
}

static void SetupUnboxingInfoOfParameter(const Function& function,
                                         intptr_t param_index,
                                         const UnboxingInfoMetadata* metadata) {
  const intptr_t param_pos =
      param_index + (function.HasThisParameter() ? 1 : 0);

  if (param_pos < function.maximum_unboxed_parameter_count()) {
    switch (metadata->unboxed_args_info[param_index]) {
      case UnboxingInfoMetadata::kUnboxedIntCandidate:
        function.set_unboxed_integer_parameter_at(param_pos);
        break;
      case UnboxingInfoMetadata::kUnboxedDoubleCandidate:
        if (FlowGraphCompiler::SupportsUnboxedDoubles()) {
          function.set_unboxed_double_parameter_at(param_pos);
        }
        break;
      case UnboxingInfoMetadata::kUnboxingCandidate:
        UNREACHABLE();
        break;
      case UnboxingInfoMetadata::kBoxed:
        break;
      default:
        UNREACHABLE();
        break;
    }
  }
}

static void SetupUnboxingInfoOfReturnValue(
    const Function& function,
    const UnboxingInfoMetadata* metadata) {
  switch (metadata->return_info) {
    case UnboxingInfoMetadata::kUnboxedIntCandidate:
      function.set_unboxed_integer_return();
      break;
    case UnboxingInfoMetadata::kUnboxedDoubleCandidate:
      if (FlowGraphCompiler::SupportsUnboxedDoubles()) {
        function.set_unboxed_double_return();
      }
      break;
    case UnboxingInfoMetadata::kUnboxingCandidate:
      UNREACHABLE();
      break;
    case UnboxingInfoMetadata::kBoxed:
      break;
    default:
      UNREACHABLE();
      break;
  }
}

void TypeTranslator::SetupUnboxingInfoMetadata(const Function& function,
                                               intptr_t library_kernel_offset) {
  const intptr_t kernel_offset =
      function.kernel_offset() + library_kernel_offset;
  const auto unboxing_info =
      unboxing_info_metadata_helper_.GetUnboxingInfoMetadata(kernel_offset);

  if (FLAG_precompiled_mode && unboxing_info != nullptr) {
    for (intptr_t i = 0; i < unboxing_info->unboxed_args_info.length(); i++) {
      SetupUnboxingInfoOfParameter(function, i, unboxing_info);
    }
    SetupUnboxingInfoOfReturnValue(function, unboxing_info);
  }
}

void TypeTranslator::SetupUnboxingInfoMetadataForFieldAccessors(
    const Function& field_accessor,
    intptr_t library_kernel_offset) {
  const intptr_t kernel_offset =
      field_accessor.kernel_offset() + library_kernel_offset;
  const auto unboxing_info =
      unboxing_info_metadata_helper_.GetUnboxingInfoMetadata(kernel_offset);

  if (FLAG_precompiled_mode && unboxing_info != nullptr) {
    if (field_accessor.IsImplicitSetterFunction()) {
      for (intptr_t i = 0; i < unboxing_info->unboxed_args_info.length(); i++) {
        SetupUnboxingInfoOfParameter(field_accessor, i, unboxing_info);
      }
    } else {
      ASSERT(field_accessor.IsImplicitGetterFunction() ||
             field_accessor.IsImplicitStaticGetterFunction());
      SetupUnboxingInfoOfReturnValue(field_accessor, unboxing_info);
    }
  }
}

void TypeTranslator::SetupFunctionParameters(
    const Class& klass,
    const Function& function,
    bool is_method,
    bool is_closure,
    FunctionNodeHelper* function_node_helper) {
  ASSERT(!(is_method && is_closure));
  bool is_factory = function.IsFactory();
  intptr_t extra_parameters = (is_method || is_closure || is_factory) ? 1 : 0;

  const FunctionType& signature = FunctionType::Handle(Z, function.signature());
  ASSERT(!signature.IsNull());
  intptr_t type_parameter_count = 0;
  if (!is_factory) {
    type_parameter_count = helper_->ReadListLength();
    LoadAndSetupTypeParameters(active_class_, function, Class::Handle(Z),
                               signature, type_parameter_count);
    function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters);
  }

  ActiveTypeParametersScope scope(active_class_, function, &signature, Z);

  if (!is_factory) {
    LoadAndSetupBounds(active_class_, function, Class::Handle(Z), signature,
                       type_parameter_count);
    function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters);
  }

  function_node_helper->ReadUntilExcluding(
      FunctionNodeHelper::kPositionalParameters);

  intptr_t required_parameter_count =
      function_node_helper->required_parameter_count_;
  intptr_t total_parameter_count = function_node_helper->total_parameter_count_;

  intptr_t positional_parameter_count =
      helper_->ReadListLength();  // read list length.

  intptr_t named_parameter_count =
      total_parameter_count - positional_parameter_count;

  signature.set_num_fixed_parameters(extra_parameters +
                                     required_parameter_count);
  if (named_parameter_count > 0) {
    signature.SetNumOptionalParameters(named_parameter_count, false);
  } else {
    signature.SetNumOptionalParameters(
        positional_parameter_count - required_parameter_count, true);
  }
  intptr_t parameter_count = extra_parameters + total_parameter_count;

  intptr_t pos = 0;
  if (parameter_count > 0) {
    signature.set_parameter_types(
        Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
    function.CreateNameArray();
    signature.CreateNameArrayIncludingFlags();
    if (is_method) {
      ASSERT(!klass.IsNull());
      signature.SetParameterTypeAt(pos, H.GetDeclarationType(klass));
      function.SetParameterNameAt(pos, Symbols::This());
      pos++;
    } else if (is_closure) {
      signature.SetParameterTypeAt(pos, AbstractType::dynamic_type());
      function.SetParameterNameAt(pos, Symbols::ClosureParameter());
      pos++;
    } else if (is_factory) {
      signature.SetParameterTypeAt(pos, AbstractType::dynamic_type());
      function.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter());
      pos++;
    }
  } else {
    ASSERT(!is_method && !is_closure && !is_factory);
  }

  const Library& lib = Library::Handle(Z, active_class_->klass->library());
  for (intptr_t i = 0; i < positional_parameter_count; ++i, ++pos) {
    // Read ith variable declaration.
    VariableDeclarationHelper helper(helper_);
    helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
    // The required flag should only be set on named parameters.
    ASSERT(!helper.IsRequired());
    const AbstractType& type = BuildTypeWithoutFinalization();  // read type.
    Tag tag = helper_->ReadTag();  // read (first part of) initializer.
    if (tag == kSomething) {
      helper_->SkipExpression();  // read (actual) initializer.
    }

    signature.SetParameterTypeAt(pos, type);
    function.SetParameterNameAt(pos, H.DartIdentifier(lib, helper.name_index_));
  }

  intptr_t named_parameter_count_check =
      helper_->ReadListLength();  // read list length.
  ASSERT(named_parameter_count_check == named_parameter_count);
  for (intptr_t i = 0; i < named_parameter_count; ++i, ++pos) {
    // Read ith variable declaration.
    VariableDeclarationHelper helper(helper_);
    helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
    const AbstractType& type = BuildTypeWithoutFinalization();  // read type.
    Tag tag = helper_->ReadTag();  // read (first part of) initializer.
    if (tag == kSomething) {
      helper_->SkipExpression();  // read (actual) initializer.
    }

    signature.SetParameterTypeAt(pos, type);
    signature.SetParameterNameAt(pos,
                                 H.DartIdentifier(lib, helper.name_index_));
    if (helper.IsRequired()) {
      signature.SetIsRequiredAt(pos);
    }
  }
  signature.FinalizeNameArray();

  function_node_helper->SetJustRead(FunctionNodeHelper::kNamedParameters);

  // The result type for generative constructors has already been set.
  if (!function.IsGenerativeConstructor()) {
    const AbstractType& return_type =
        BuildTypeWithoutFinalization();  // read return type.
    signature.set_result_type(return_type);
    function_node_helper->SetJustRead(FunctionNodeHelper::kReturnType);
  }
}

}  // namespace kernel
}  // namespace dart
