// Copyright (c) 2012, 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/object.h"

#include <memory>

#include "compiler/method_recognizer.h"
#include "include/dart_api.h"
#include "lib/integers.h"
#include "lib/stacktrace.h"
#include "platform/assert.h"
#include "platform/text_buffer.h"
#include "platform/unaligned.h"
#include "platform/unicode.h"
#include "vm/bit_vector.h"
#include "vm/bootstrap.h"
#include "vm/bytecode_reader.h"
#include "vm/canonical_tables.h"
#include "vm/class_finalizer.h"
#include "vm/class_id.h"
#include "vm/closure_functions_cache.h"
#include "vm/code_comments.h"
#include "vm/code_descriptors.h"
#include "vm/code_observers.h"
#include "vm/compiler/assembler/disassembler.h"
#include "vm/compiler/assembler/disassembler_kbc.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/compiler/runtime_api.h"
#include "vm/cpu.h"
#include "vm/dart.h"
#include "vm/dart_api_state.h"
#include "vm/dart_entry.h"
#include "vm/datastream.h"
#include "vm/debugger.h"
#include "vm/deopt_instructions.h"
#include "vm/double_conversion.h"
#include "vm/elf.h"
#include "vm/exceptions.h"
#include "vm/growable_array.h"
#include "vm/hash.h"
#include "vm/hash_table.h"
#include "vm/heap/become.h"
#include "vm/heap/heap.h"
#include "vm/heap/sampler.h"
#include "vm/heap/weak_code.h"
#include "vm/image_snapshot.h"
#include "vm/isolate_reload.h"
#include "vm/kernel.h"
#include "vm/kernel_binary.h"
#include "vm/kernel_isolate.h"
#include "vm/kernel_loader.h"
#include "vm/line_starts_reader.h"
#include "vm/log.h"
#include "vm/native_symbol.h"
#include "vm/object_graph.h"
#include "vm/object_store.h"
#include "vm/os.h"
#include "vm/parser.h"
#include "vm/profiler.h"
#include "vm/regexp/regexp.h"
#include "vm/resolver.h"
#include "vm/reusable_handles.h"
#include "vm/reverse_pc_lookup_cache.h"
#include "vm/runtime_entry.h"
#include "vm/scopes.h"
#include "vm/stack_frame.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
#include "vm/tags.h"
#include "vm/thread_registry.h"
#include "vm/timeline.h"
#include "vm/type_testing_stubs.h"
#include "vm/zone_text_buffer.h"

#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/aot/precompiler.h"
#include "vm/compiler/assembler/assembler.h"
#include "vm/compiler/backend/code_statistics.h"
#include "vm/compiler/compiler_state.h"
#include "vm/compiler/frontend/kernel_fingerprints.h"
#include "vm/compiler/frontend/kernel_translation_helper.h"
#include "vm/compiler/intrinsifier.h"
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

namespace dart {

DEFINE_FLAG(uint64_t,
            huge_method_cutoff_in_code_size,
            200000,
            "Huge method cutoff in unoptimized code size (in bytes).");
DEFINE_FLAG(
    bool,
    show_internal_names,
    false,
    "Show names of internal classes (e.g. \"OneByteString\") in error messages "
    "instead of showing the corresponding interface names (e.g. \"String\"). "
    "Also show legacy nullability in type names.");

DEFINE_FLAG(bool,
            remove_script_timestamps_for_test,
            false,
            "Remove script timestamps to allow for deterministic testing.");

#if !defined(DART_PRECOMPILED_RUNTIME)
DEFINE_FLAG(bool, use_register_cc, true, "Use register calling conventions");
#endif

DECLARE_FLAG(bool, intrinsify);
DECLARE_FLAG(bool, trace_deoptimization);
DECLARE_FLAG(bool, trace_deoptimization_verbose);
DECLARE_FLAG(bool, trace_reload);
DECLARE_FLAG(bool, write_protect_code);
DECLARE_FLAG(bool, precompiled_mode);
DECLARE_FLAG(int, max_polymorphic_checks);

static const char* const kGetterPrefix = "get:";
static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix);
static const char* const kSetterPrefix = "set:";
static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix);
static const char* const kInitPrefix = "init:";
static const intptr_t kInitPrefixLength = strlen(kInitPrefix);

// A cache of VM heap allocated preinitialized empty ic data entry arrays.
ArrayPtr ICData::cached_icdata_arrays_[kCachedICDataArrayCount];

cpp_vtable Object::builtin_vtables_[kNumPredefinedCids] = {};

// These are initialized to a value that will force an illegal memory access if
// they are being used.
#if defined(RAW_NULL)
#error RAW_NULL should not be defined.
#endif
#define RAW_NULL static_cast<uword>(kHeapObjectTag)

#define CHECK_ERROR(error)                                                     \
  {                                                                            \
    ErrorPtr err = (error);                                                    \
    if (err != Error::null()) {                                                \
      return err;                                                              \
    }                                                                          \
  }

#define DEFINE_SHARED_READONLY_HANDLE(Type, name)                              \
  Type* Object::name##_ = nullptr;
SHARED_READONLY_HANDLES_LIST(DEFINE_SHARED_READONLY_HANDLE)
#undef DEFINE_SHARED_READONLY_HANDLE

ObjectPtr Object::null_ = static_cast<ObjectPtr>(RAW_NULL);
BoolPtr Object::true_ = static_cast<BoolPtr>(RAW_NULL);
BoolPtr Object::false_ = static_cast<BoolPtr>(RAW_NULL);
ClassPtr Object::class_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::dynamic_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::void_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::type_parameters_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::type_arguments_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::patch_class_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::function_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::closure_data_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::ffi_trampoline_data_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::field_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::script_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::library_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::namespace_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::kernel_program_info_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::code_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::instructions_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::instructions_section_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::instructions_table_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::object_pool_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::pc_descriptors_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::code_source_map_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::compressed_stackmaps_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::var_descriptors_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::exception_handlers_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::context_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::context_scope_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::bytecode_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::sentinel_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::singletargetcache_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::unlinkedcall_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::monomorphicsmiablecall_class_ =
    static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::icdata_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::megamorphic_cache_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::subtypetestcache_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::loadingunit_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::api_error_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::language_error_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::unhandled_exception_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::unwind_error_class_ = static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::weak_serialization_reference_class_ =
    static_cast<ClassPtr>(RAW_NULL);
ClassPtr Object::weak_array_class_ = static_cast<ClassPtr>(RAW_NULL);

static void AppendSubString(BaseTextBuffer* buffer,
                            const char* name,
                            intptr_t start_pos,
                            intptr_t len) {
  buffer->Printf("%.*s", static_cast<int>(len), &name[start_pos]);
}

// Used to define setters and getters for untagged object fields that are
// defined with the WSR_COMPRESSED_POINTER_FIELD macro. See
// PRECOMPILER_WSR_FIELD_DECLARATION in object.h for more information.
#if defined(DART_PRECOMPILER)
#define PRECOMPILER_WSR_FIELD_DEFINITION(Class, Type, Name)                    \
  Type##Ptr Class::Name() const {                                              \
    return Type::RawCast(WeakSerializationReference::Unwrap(untag()->Name())); \
  }
#else
#define PRECOMPILER_WSR_FIELD_DEFINITION(Class, Type, Name)                    \
  void Class::set_##Name(const Type& value) const {                            \
    untag()->set_##Name(value.ptr());                                          \
  }
#endif

PRECOMPILER_WSR_FIELD_DEFINITION(ClosureData, Function, parent_function)
PRECOMPILER_WSR_FIELD_DEFINITION(Function, FunctionType, signature)

#undef PRECOMPILER_WSR_FIELD_DEFINITION

#if defined(_MSC_VER)
#define TRACE_TYPE_CHECKS_VERBOSE(format, ...)                                 \
  if (FLAG_trace_type_checks_verbose) {                                        \
    OS::PrintErr(format, __VA_ARGS__);                                         \
  }
#else
#define TRACE_TYPE_CHECKS_VERBOSE(format, ...)                                 \
  if (FLAG_trace_type_checks_verbose) {                                        \
    OS::PrintErr(format, ##__VA_ARGS__);                                       \
  }
#endif

// Remove private keys, but retain getter/setter/constructor/mixin manglings.
StringPtr String::RemovePrivateKey(const String& name) {
  ASSERT(name.IsOneByteString());
  GrowableArray<uint8_t> without_key(name.Length());
  intptr_t i = 0;
  while (i < name.Length()) {
    while (i < name.Length()) {
      uint8_t c = name.CharAt(i++);
      if (c == '@') break;
      without_key.Add(c);
    }
    while (i < name.Length()) {
      uint8_t c = name.CharAt(i);
      if ((c < '0') || (c > '9')) break;
      i++;
    }
  }

  return String::FromLatin1(without_key.data(), without_key.length());
}

// Takes a vm internal name and makes it suitable for external user.
//
// Examples:
//
// Internal getter and setter prefixes are changed:
//
//   get:foo -> foo
//   set:foo -> foo=
//
// Private name mangling is removed, possibly multiple times:
//
//   _ReceivePortImpl@709387912 -> _ReceivePortImpl
//   _ReceivePortImpl@709387912._internal@709387912 ->
//      _ReceivePortImpl._internal
//   _C@6328321&_E@6328321&_F@6328321 -> _C&_E&_F
//
// The trailing . on the default constructor name is dropped:
//
//   List. -> List
//
// And so forth:
//
//   get:foo@6328321 -> foo
//   _MyClass@6328321. -> _MyClass
//   _MyClass@6328321.named -> _MyClass.named
//
// For extension methods the following demangling is done
//   ext|func -> ext.func (instance extension method)
//   ext|get#prop -> ext.prop (instance extension getter)
//   ext|set#prop -> ext.prop= (instance extension setter)
//   ext|sfunc -> ext.sfunc (static extension method)
//   get:ext|sprop -> ext.sprop (static extension getter)
//   set:ext|sprop -> ext.sprop= (static extension setter)
//
const char* String::ScrubName(const String& name, bool is_extension) {
  Thread* thread = Thread::Current();
  NoSafepointScope no_safepoint(thread);
  Zone* zone = thread->zone();
  ZoneTextBuffer printer(zone);

#if !defined(DART_PRECOMPILED_RUNTIME)
  if (name.Equals(Symbols::TopLevel())) {
    // Name of invisible top-level class.
    return "";
  }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

  const char* cname = name.ToCString();
  ASSERT(strlen(cname) == static_cast<size_t>(name.Length()));
  const intptr_t name_len = name.Length();
  // First remove all private name mangling and if 'is_extension' is true
  // substitute the first '|' character with '.'.
  intptr_t start_pos = 0;
  intptr_t sum_segment_len = 0;
  for (intptr_t i = 0; i < name_len; i++) {
    if ((cname[i] == '@') && ((i + 1) < name_len) && (cname[i + 1] >= '0') &&
        (cname[i + 1] <= '9')) {
      // Append the current segment to the unmangled name.
      const intptr_t segment_len = i - start_pos;
      sum_segment_len += segment_len;
      AppendSubString(&printer, cname, start_pos, segment_len);
      // Advance until past the name mangling. The private keys are only
      // numbers so we skip until the first non-number.
      i++;  // Skip the '@'.
      while ((i < name.Length()) && (name.CharAt(i) >= '0') &&
             (name.CharAt(i) <= '9')) {
        i++;
      }
      start_pos = i;
      i--;  // Account for for-loop increment.
    } else if (is_extension && cname[i] == '|') {
      // Append the current segment to the unmangled name.
      const intptr_t segment_len = i - start_pos;
      AppendSubString(&printer, cname, start_pos, segment_len);
      // Append the '.' character (replaces '|' with '.').
      AppendSubString(&printer, ".", 0, 1);
      start_pos = i + 1;
      // Account for length of segments added so far.
      sum_segment_len += (segment_len + 1);
    }
  }

  const char* unmangled_name = nullptr;
  if (start_pos == 0) {
    // No name unmangling needed, reuse the name that was passed in.
    unmangled_name = cname;
    sum_segment_len = name_len;
  } else if (name.Length() != start_pos) {
    // Append the last segment.
    const intptr_t segment_len = name.Length() - start_pos;
    sum_segment_len += segment_len;
    AppendSubString(&printer, cname, start_pos, segment_len);
  }
  if (unmangled_name == nullptr) {
    // Merge unmangled_segments.
    unmangled_name = printer.buffer();
  }

  printer.Clear();
  intptr_t start = 0;
  intptr_t len = sum_segment_len;
  bool is_setter = false;
  if (is_extension) {
    // First scan till we see the '.' character.
    for (intptr_t i = 0; i < len; i++) {
      if (unmangled_name[i] == '.') {
        intptr_t slen = i + 1;
        intptr_t plen = slen - start;
        AppendSubString(&printer, unmangled_name, start, plen);
        unmangled_name += slen;
        len -= slen;
        break;
      } else if (unmangled_name[i] == ':') {
        if (start != 0) {
          // Reset and break.
          start = 0;
          is_setter = false;
          break;
        }
        if (unmangled_name[0] == 's') {
          is_setter = true;
        }
        start = i + 1;
      }
    }
  }
  intptr_t dot_pos = -1;  // Position of '.' in the name, if any.
  start = 0;
  for (intptr_t i = start; i < len; i++) {
    if (unmangled_name[i] == ':' ||
        (is_extension && unmangled_name[i] == '#')) {
      if (start != 0) {
        // Reset and break.
        start = 0;
        dot_pos = -1;
        break;
      }
      ASSERT(start == 0);  // Only one : is possible in getters or setters.
      if (unmangled_name[0] == 's') {
        ASSERT(!is_setter);
        is_setter = true;
      }
      start = i + 1;
    } else if (unmangled_name[i] == '.') {
      if (dot_pos != -1) {
        // Reset and break.
        start = 0;
        dot_pos = -1;
        break;
      }
      ASSERT(dot_pos == -1);  // Only one dot is supported.
      dot_pos = i;
    }
  }

  if (!is_extension && (start == 0) && (dot_pos == -1)) {
    // This unmangled_name is fine as it is.
    return unmangled_name;
  }

  // Drop the trailing dot if needed.
  intptr_t end = ((dot_pos + 1) == len) ? dot_pos : len;

  intptr_t substr_len = end - start;
  AppendSubString(&printer, unmangled_name, start, substr_len);
  if (is_setter) {
    const char* equals = Symbols::Equals().ToCString();
    const intptr_t equals_len = strlen(equals);
    AppendSubString(&printer, equals, 0, equals_len);
  }

  return printer.buffer();
}

StringPtr String::ScrubNameRetainPrivate(const String& name,
                                         bool is_extension) {
#if !defined(DART_PRECOMPILED_RUNTIME)
  intptr_t len = name.Length();
  intptr_t start = 0;
  intptr_t at_pos = -1;  // Position of '@' in the name, if any.
  bool is_setter = false;

  String& result = String::Handle();

  // If extension strip out the leading prefix e.g" ext|func would strip out
  // 'ext|'.
  if (is_extension) {
    // First scan till we see the '|' character.
    for (intptr_t i = 0; i < len; i++) {
      if (name.CharAt(i) == '|') {
        result = String::SubString(name, start, (i - start));
        result = String::Concat(result, Symbols::Dot());
        start = i + 1;
        break;
      } else if (name.CharAt(i) == ':') {
        if (start != 0) {
          // Reset and break.
          start = 0;
          is_setter = false;
          break;
        }
        if (name.CharAt(0) == 's') {
          is_setter = true;
        }
        start = i + 1;
      }
    }
  }

  for (intptr_t i = start; i < len; i++) {
    if (name.CharAt(i) == ':' || (is_extension && name.CharAt(i) == '#')) {
      // Only one : is possible in getters or setters.
      ASSERT(is_extension || start == 0);
      if (name.CharAt(start) == 's') {
        is_setter = true;
      }
      start = i + 1;
    } else if (name.CharAt(i) == '@') {
      // Setters should have only one @ so we know where to put the =.
      ASSERT(!is_setter || (at_pos == -1));
      at_pos = i;
    }
  }

  if (start == 0) {
    // This unmangled_name is fine as it is.
    return name.ptr();
  }

  if (is_extension) {
    const String& fname =
        String::Handle(String::SubString(name, start, (len - start)));
    result = String::Concat(result, fname);
  } else {
    result = String::SubString(name, start, (len - start));
  }

  if (is_setter) {
    // Setters need to end with '='.
    if (at_pos == -1) {
      return String::Concat(result, Symbols::Equals());
    } else {
      const String& pre_at =
          String::Handle(String::SubString(result, 0, at_pos - 4));
      const String& post_at =
          String::Handle(String::SubString(name, at_pos, len - at_pos));
      result = String::Concat(pre_at, Symbols::Equals());
      result = String::Concat(result, post_at);
    }
  }

  return result.ptr();
#endif                // !defined(DART_PRECOMPILED_RUNTIME)
  return name.ptr();  // In AOT, return argument unchanged.
}

template <typename type>
static bool IsSpecialCharacter(type value) {
  return ((value == '"') || (value == '\n') || (value == '\f') ||
          (value == '\b') || (value == '\t') || (value == '\v') ||
          (value == '\r') || (value == '\\') || (value == '$'));
}

static inline bool IsAsciiNonprintable(int32_t c) {
  return ((0 <= c) && (c < 32)) || (c == 127);
}

static int32_t EscapeOverhead(int32_t c) {
  if (IsSpecialCharacter(c)) {
    return 1;  // 1 additional byte for the backslash.
  } else if (IsAsciiNonprintable(c)) {
    return 3;  // 3 additional bytes to encode c as \x00.
  }
  return 0;
}

template <typename type>
static type SpecialCharacter(type value) {
  if (value == '"') {
    return '"';
  } else if (value == '\n') {
    return 'n';
  } else if (value == '\f') {
    return 'f';
  } else if (value == '\b') {
    return 'b';
  } else if (value == '\t') {
    return 't';
  } else if (value == '\v') {
    return 'v';
  } else if (value == '\r') {
    return 'r';
  } else if (value == '\\') {
    return '\\';
  } else if (value == '$') {
    return '$';
  }
  UNREACHABLE();
  return '\0';
}

#if defined(DART_DYNAMIC_MODULES)
static BytecodePtr CreateVMInternalBytecode(KernelBytecode::Opcode opcode) {
  const KBCInstr* instructions = nullptr;
  intptr_t instructions_size = 0;

  KernelBytecode::GetVMInternalBytecodeInstructions(opcode, &instructions,
                                                    &instructions_size);

  const auto& bytecode = Bytecode::Handle(
      Bytecode::New(reinterpret_cast<uword>(instructions), instructions_size,
                    -1, TypedDataBase::Handle(), Object::empty_object_pool()));
  bytecode.set_pc_descriptors(Object::empty_descriptors());
  bytecode.set_exception_handlers(Object::empty_exception_handlers());
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
  bytecode.set_var_descriptors(Object::empty_var_descriptors());
#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
  return bytecode.ptr();
}
#endif  // defined(DART_DYNAMIC_MODULES)

void Object::InitNullAndBool(IsolateGroup* isolate_group) {
  // Should only be run by the vm isolate.
  ASSERT(isolate_group == Dart::vm_isolate_group());
  Thread* thread = Thread::Current();
  auto heap = isolate_group->heap();

  // TODO(iposva): NoSafepointScope needs to be added here.
  ASSERT(class_class() == null_);

  // Allocate and initialize the null instance.
  // 'null_' must be the first object allocated as it is used in allocation to
  // clear the pointer fields of objects.
  {
    uword address =
        heap->Allocate(thread, Instance::InstanceSize(), Heap::kOld);
    null_ = static_cast<InstancePtr>(address + kHeapObjectTag);
    InitializeObjectVariant<Instance>(address, kNullCid);
    null_->untag()->SetCanonical();
  }

  // Allocate and initialize the bool instances.
  // These must be allocated such that at kBoolValueBitPosition, the address
  // of true is 0 and the address of false is 1, and their addresses are
  // otherwise identical.
  {
    // Allocate a dummy bool object to give true the desired alignment.
    uword address = heap->Allocate(thread, Bool::InstanceSize(), Heap::kOld);
    InitializeObject<Bool>(address);
    static_cast<BoolPtr>(address + kHeapObjectTag)->untag()->value_ = false;
  }
  {
    // Allocate true.
    uword address = heap->Allocate(thread, Bool::InstanceSize(), Heap::kOld);
    true_ = static_cast<BoolPtr>(address + kHeapObjectTag);
    InitializeObject<Bool>(address);
    true_->untag()->value_ = true;
    true_->untag()->SetCanonical();
  }
  {
    // Allocate false.
    uword address = heap->Allocate(thread, Bool::InstanceSize(), Heap::kOld);
    false_ = static_cast<BoolPtr>(address + kHeapObjectTag);
    InitializeObject<Bool>(address);
    false_->untag()->value_ = false;
    false_->untag()->SetCanonical();
  }

  // Check that the objects have been allocated at appropriate addresses.
  ASSERT(static_cast<uword>(true_) ==
         static_cast<uword>(null_) + kTrueOffsetFromNull);
  ASSERT(static_cast<uword>(false_) ==
         static_cast<uword>(null_) + kFalseOffsetFromNull);
  ASSERT((static_cast<uword>(true_) & kBoolValueMask) == 0);
  ASSERT((static_cast<uword>(false_) & kBoolValueMask) != 0);
  ASSERT(static_cast<uword>(false_) ==
         (static_cast<uword>(true_) | kBoolValueMask));
  ASSERT((static_cast<uword>(null_) & kBoolVsNullMask) == 0);
  ASSERT((static_cast<uword>(true_) & kBoolVsNullMask) != 0);
  ASSERT((static_cast<uword>(false_) & kBoolVsNullMask) != 0);
}

void Object::InitVtables() {
  {
    Object fake_handle;
    builtin_vtables_[kObjectCid] = fake_handle.vtable();
  }

#define INIT_VTABLE(clazz)                                                     \
  {                                                                            \
    clazz fake_handle;                                                         \
    builtin_vtables_[k##clazz##Cid] = fake_handle.vtable();                    \
  }
  CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(INIT_VTABLE)
  INIT_VTABLE(GrowableObjectArray)
#undef INIT_VTABLE

#define INIT_VTABLE(clazz)                                                     \
  {                                                                            \
    Map fake_handle;                                                           \
    builtin_vtables_[k##clazz##Cid] = fake_handle.vtable();                    \
  }
  CLASS_LIST_MAPS(INIT_VTABLE)
#undef INIT_VTABLE

#define INIT_VTABLE(clazz)                                                     \
  {                                                                            \
    Set fake_handle;                                                           \
    builtin_vtables_[k##clazz##Cid] = fake_handle.vtable();                    \
  }
  CLASS_LIST_SETS(INIT_VTABLE)
#undef INIT_VTABLE

#define INIT_VTABLE(clazz)                                                     \
  {                                                                            \
    Array fake_handle;                                                         \
    builtin_vtables_[k##clazz##Cid] = fake_handle.vtable();                    \
  }
  CLASS_LIST_FIXED_LENGTH_ARRAYS(INIT_VTABLE)
#undef INIT_VTABLE

#define INIT_VTABLE(clazz)                                                     \
  {                                                                            \
    String fake_handle;                                                        \
    builtin_vtables_[k##clazz##Cid] = fake_handle.vtable();                    \
  }
  CLASS_LIST_STRINGS(INIT_VTABLE)
#undef INIT_VTABLE

  {
    Instance fake_handle;
    builtin_vtables_[kFfiNativeTypeCid] = fake_handle.vtable();
  }

#define INIT_VTABLE(clazz)                                                     \
  {                                                                            \
    Instance fake_handle;                                                      \
    builtin_vtables_[kFfi##clazz##Cid] = fake_handle.vtable();                 \
  }
  CLASS_LIST_FFI_TYPE_MARKER(INIT_VTABLE)
#undef INIT_VTABLE

  {
    Instance fake_handle;
    builtin_vtables_[kFfiNativeFunctionCid] = fake_handle.vtable();
  }

  {
    Pointer fake_handle;
    builtin_vtables_[kPointerCid] = fake_handle.vtable();
  }

  {
    DynamicLibrary fake_handle;
    builtin_vtables_[kDynamicLibraryCid] = fake_handle.vtable();
  }

#define INIT_VTABLE(clazz)                                                     \
  {                                                                            \
    TypedData fake_internal_handle;                                            \
    builtin_vtables_[kTypedData##clazz##Cid] = fake_internal_handle.vtable();  \
    TypedDataView fake_view_handle;                                            \
    builtin_vtables_[kTypedData##clazz##ViewCid] = fake_view_handle.vtable();  \
    builtin_vtables_[kUnmodifiableTypedData##clazz##ViewCid] =                 \
        fake_view_handle.vtable();                                             \
    ExternalTypedData fake_external_handle;                                    \
    builtin_vtables_[kExternalTypedData##clazz##Cid] =                         \
        fake_external_handle.vtable();                                         \
  }
  CLASS_LIST_TYPED_DATA(INIT_VTABLE)
#undef INIT_VTABLE

  {
    TypedDataView fake_handle;
    builtin_vtables_[kByteDataViewCid] = fake_handle.vtable();
    builtin_vtables_[kUnmodifiableByteDataViewCid] = fake_handle.vtable();
  }

  {
    Instance fake_handle;
    builtin_vtables_[kByteBufferCid] = fake_handle.vtable();
    builtin_vtables_[kNullCid] = fake_handle.vtable();
    builtin_vtables_[kDynamicCid] = fake_handle.vtable();
    builtin_vtables_[kVoidCid] = fake_handle.vtable();
    builtin_vtables_[kNeverCid] = fake_handle.vtable();
  }
}

void Object::Init(IsolateGroup* isolate_group) {
  // Should only be run by the vm isolate.
  ASSERT(isolate_group == Dart::vm_isolate_group());
  Heap* heap = isolate_group->heap();
  Thread* thread = Thread::Current();
  ASSERT(thread != nullptr);
  // Ensure lock checks in setters are happy.
  SafepointWriteRwLocker ml(thread, isolate_group->program_lock());

  InitVtables();

// Allocate the read only object handles here.
#define INITIALIZE_SHARED_READONLY_HANDLE(Type, name)                          \
  name##_ = Type::ReadOnlyHandle();
  SHARED_READONLY_HANDLES_LIST(INITIALIZE_SHARED_READONLY_HANDLE)
#undef INITIALIZE_SHARED_READONLY_HANDLE

  *null_object_ = Object::null();
  *null_class_ = Class::null();
  *null_array_ = Array::null();
  *null_string_ = String::null();
  *null_instance_ = Instance::null();
  *null_function_ = Function::null();
  *null_function_type_ = FunctionType::null();
  *null_record_type_ = RecordType::null();
  *null_type_arguments_ = TypeArguments::null();
  *null_closure_ = Closure::null();
  *empty_type_arguments_ = TypeArguments::null();
  *null_abstract_type_ = AbstractType::null();
  *null_compressed_stackmaps_ = CompressedStackMaps::null();
  *bool_true_ = true_;
  *bool_false_ = false_;

  // Initialize the empty array and empty instantiations cache array handles to
  // null_ in order to be able to check if the empty and zero arrays were
  // allocated (RAW_NULL is not available).
  *empty_array_ = Array::null();
  *empty_instantiations_cache_array_ = Array::null();
  *empty_subtype_test_cache_array_ = Array::null();

  Class& cls = Class::Handle();

  // Allocate and initialize the class class.
  {
    intptr_t size = Class::InstanceSize();
    uword address = heap->Allocate(thread, size, Heap::kOld);
    class_class_ = static_cast<ClassPtr>(address + kHeapObjectTag);
    InitializeObject<Class>(address);

    Class fake;
    // Initialization from Class::New<Class>.
    // Directly set ptr_ to break a circular dependency: SetRaw will attempt
    // to lookup class class in the class table where it is not registered yet.
    cls.ptr_ = class_class_;
    ASSERT(builtin_vtables_[kClassCid] == fake.vtable());
    cls.set_instance_size(
        Class::InstanceSize(),
        compiler::target::RoundedAllocationSize(RTN::Class::InstanceSize()));
    const intptr_t host_next_field_offset = Class::NextFieldOffset();
    const intptr_t target_next_field_offset = RTN::Class::NextFieldOffset();
    cls.set_next_field_offset(host_next_field_offset, target_next_field_offset);
    cls.set_id(Class::kClassId);
    cls.set_state_bits(0);
    cls.set_is_allocate_finalized();
    cls.set_is_declaration_loaded();
    cls.set_is_type_finalized();
    cls.set_type_arguments_field_offset_in_words(Class::kNoTypeArguments,
                                                 RTN::Class::kNoTypeArguments);
    cls.set_num_type_arguments_unsafe(0);
    cls.set_num_native_fields(0);
    cls.InitEmptyFields();
    isolate_group->class_table()->Register(cls);
  }

  // Allocate and initialize the null class.
  cls = Class::New<Instance, RTN::Instance>(kNullCid, isolate_group);
  cls.set_num_type_arguments_unsafe(0);
  isolate_group->object_store()->set_null_class(cls);

  // Allocate and initialize Never class.
  cls = Class::New<Instance, RTN::Instance>(kNeverCid, isolate_group);
  cls.set_num_type_arguments_unsafe(0);
  cls.set_is_allocate_finalized();
  cls.set_is_declaration_loaded();
  cls.set_is_type_finalized();
  isolate_group->object_store()->set_never_class(cls);

  // Allocate and initialize the free list element class.
  cls = Class::New<FreeListElement::FakeInstance,
                   RTN::FreeListElement::FakeInstance>(kFreeListElement,
                                                       isolate_group);
  cls.set_num_type_arguments_unsafe(0);
  cls.set_is_allocate_finalized();
  cls.set_is_declaration_loaded();
  cls.set_is_type_finalized();

  // Allocate and initialize the forwarding corpse class.
  cls = Class::New<ForwardingCorpse::FakeInstance,
                   RTN::ForwardingCorpse::FakeInstance>(kForwardingCorpse,
                                                        isolate_group);
  cls.set_num_type_arguments_unsafe(0);
  cls.set_is_allocate_finalized();
  cls.set_is_declaration_loaded();
  cls.set_is_type_finalized();

  // Allocate and initialize Sentinel class.
  cls = Class::New<Sentinel, RTN::Sentinel>(isolate_group);
  sentinel_class_ = cls.ptr();

  // Allocate and initialize the sentinel values.
  {
    *sentinel_ ^= Sentinel::New();
  }

  // Allocate and initialize optimizing compiler constants.
  {
    *unknown_constant_ ^= Sentinel::New();
    *non_constant_ ^= Sentinel::New();
    *optimized_out_ ^= Sentinel::New();
  }

  // Allocate the remaining VM internal classes.
  cls = Class::New<TypeParameters, RTN::TypeParameters>(isolate_group);
  type_parameters_class_ = cls.ptr();

  cls = Class::New<TypeArguments, RTN::TypeArguments>(isolate_group);
  type_arguments_class_ = cls.ptr();

  cls = Class::New<PatchClass, RTN::PatchClass>(isolate_group);
  patch_class_class_ = cls.ptr();

  cls = Class::New<Function, RTN::Function>(isolate_group);
  function_class_ = cls.ptr();

  cls = Class::New<ClosureData, RTN::ClosureData>(isolate_group);
  closure_data_class_ = cls.ptr();

  cls = Class::New<FfiTrampolineData, RTN::FfiTrampolineData>(isolate_group);
  ffi_trampoline_data_class_ = cls.ptr();

  cls = Class::New<Field, RTN::Field>(isolate_group);
  field_class_ = cls.ptr();

  cls = Class::New<Script, RTN::Script>(isolate_group);
  script_class_ = cls.ptr();

  cls = Class::New<Library, RTN::Library>(isolate_group);
  library_class_ = cls.ptr();

  cls = Class::New<Namespace, RTN::Namespace>(isolate_group);
  namespace_class_ = cls.ptr();

  cls = Class::New<KernelProgramInfo, RTN::KernelProgramInfo>(isolate_group);
  kernel_program_info_class_ = cls.ptr();

  cls = Class::New<Code, RTN::Code>(isolate_group);
  code_class_ = cls.ptr();

  cls = Class::New<Instructions, RTN::Instructions>(isolate_group);
  instructions_class_ = cls.ptr();

  cls =
      Class::New<InstructionsSection, RTN::InstructionsSection>(isolate_group);
  instructions_section_class_ = cls.ptr();

  cls = Class::New<InstructionsTable, RTN::InstructionsTable>(isolate_group);
  instructions_table_class_ = cls.ptr();

  cls = Class::New<ObjectPool, RTN::ObjectPool>(isolate_group);
  object_pool_class_ = cls.ptr();

  cls = Class::New<PcDescriptors, RTN::PcDescriptors>(isolate_group);
  pc_descriptors_class_ = cls.ptr();

  cls = Class::New<CodeSourceMap, RTN::CodeSourceMap>(isolate_group);
  code_source_map_class_ = cls.ptr();

  cls =
      Class::New<CompressedStackMaps, RTN::CompressedStackMaps>(isolate_group);
  compressed_stackmaps_class_ = cls.ptr();

  cls =
      Class::New<LocalVarDescriptors, RTN::LocalVarDescriptors>(isolate_group);
  var_descriptors_class_ = cls.ptr();

  cls = Class::New<ExceptionHandlers, RTN::ExceptionHandlers>(isolate_group);
  exception_handlers_class_ = cls.ptr();

  cls = Class::New<Context, RTN::Context>(isolate_group);
  context_class_ = cls.ptr();

  cls = Class::New<ContextScope, RTN::ContextScope>(isolate_group);
  context_scope_class_ = cls.ptr();

  cls = Class::New<Bytecode, RTN::Bytecode>(isolate_group);
  bytecode_class_ = cls.ptr();

  cls = Class::New<SingleTargetCache, RTN::SingleTargetCache>(isolate_group);
  singletargetcache_class_ = cls.ptr();

  cls = Class::New<UnlinkedCall, RTN::UnlinkedCall>(isolate_group);
  unlinkedcall_class_ = cls.ptr();

  cls = Class::New<MonomorphicSmiableCall, RTN::MonomorphicSmiableCall>(
      isolate_group);
  monomorphicsmiablecall_class_ = cls.ptr();

  cls = Class::New<ICData, RTN::ICData>(isolate_group);
  icdata_class_ = cls.ptr();

  cls = Class::New<MegamorphicCache, RTN::MegamorphicCache>(isolate_group);
  megamorphic_cache_class_ = cls.ptr();

  cls = Class::New<SubtypeTestCache, RTN::SubtypeTestCache>(isolate_group);
  subtypetestcache_class_ = cls.ptr();

  cls = Class::New<LoadingUnit, RTN::LoadingUnit>(isolate_group);
  loadingunit_class_ = cls.ptr();

  cls = Class::New<ApiError, RTN::ApiError>(isolate_group);
  api_error_class_ = cls.ptr();

  cls = Class::New<LanguageError, RTN::LanguageError>(isolate_group);
  language_error_class_ = cls.ptr();

  cls = Class::New<UnhandledException, RTN::UnhandledException>(isolate_group);
  unhandled_exception_class_ = cls.ptr();

  cls = Class::New<UnwindError, RTN::UnwindError>(isolate_group);
  unwind_error_class_ = cls.ptr();

  cls = Class::New<WeakSerializationReference, RTN::WeakSerializationReference>(
      isolate_group);
  weak_serialization_reference_class_ = cls.ptr();

  cls = Class::New<WeakArray, RTN::WeakArray>(isolate_group);
  weak_array_class_ = cls.ptr();

  ASSERT(class_class() != null_);

  // Pre-allocate classes in the vm isolate so that we can for example create a
  // symbol table and populate it with some frequently used strings as symbols.
  cls = Class::New<Array, RTN::Array>(isolate_group);
  isolate_group->object_store()->set_array_class(cls);
  cls.set_type_arguments_field_offset(Array::type_arguments_offset(),
                                      RTN::Array::type_arguments_offset());
  cls.set_num_type_arguments_unsafe(1);
  cls = Class::New<Array, RTN::Array>(kImmutableArrayCid, isolate_group);
  isolate_group->object_store()->set_immutable_array_class(cls);
  cls.set_type_arguments_field_offset(Array::type_arguments_offset(),
                                      RTN::Array::type_arguments_offset());
  cls.set_num_type_arguments_unsafe(1);
  // In order to be able to canonicalize arguments descriptors early.
  cls.set_is_prefinalized();
  cls =
      Class::New<GrowableObjectArray, RTN::GrowableObjectArray>(isolate_group);
  isolate_group->object_store()->set_growable_object_array_class(cls);
  cls.set_type_arguments_field_offset(
      GrowableObjectArray::type_arguments_offset(),
      RTN::GrowableObjectArray::type_arguments_offset());
  cls.set_num_type_arguments_unsafe(1);
  cls = Class::NewStringClass(kOneByteStringCid, isolate_group);
  isolate_group->object_store()->set_one_byte_string_class(cls);
  cls = Class::NewStringClass(kTwoByteStringCid, isolate_group);
  isolate_group->object_store()->set_two_byte_string_class(cls);
  cls = Class::New<Mint, RTN::Mint>(isolate_group);
  isolate_group->object_store()->set_mint_class(cls);
  cls = Class::New<Double, RTN::Double>(isolate_group);
  isolate_group->object_store()->set_double_class(cls);
  cls = Class::New<Float32x4, RTN::Float32x4>(isolate_group);
  isolate_group->object_store()->set_float32x4_class(cls);
  cls = Class::New<Float64x2, RTN::Float64x2>(isolate_group);
  isolate_group->object_store()->set_float64x2_class(cls);
  cls = Class::New<Int32x4, RTN::Int32x4>(isolate_group);
  isolate_group->object_store()->set_int32x4_class(cls);

  // Ensure that class kExternalTypedDataUint8ArrayCid is registered as we
  // need it when reading in the token stream of bootstrap classes in the VM
  // isolate.
  Class::NewExternalTypedDataClass(kExternalTypedDataUint8ArrayCid,
                                   isolate_group);

  // Needed for object pools of VM isolate stubs.
  Class::NewTypedDataClass(kTypedDataInt8ArrayCid, isolate_group);

  // Allocate and initialize the empty_array instance.
  {
    uword address = heap->Allocate(thread, Array::InstanceSize(0), Heap::kOld);
    InitializeObjectVariant<Array>(address, kImmutableArrayCid, 0);
    Array::initializeHandle(empty_array_,
                            static_cast<ArrayPtr>(address + kHeapObjectTag));
    empty_array_->untag()->set_length(Smi::New(0));
    empty_array_->SetCanonical();
  }

  Smi& smi = Smi::Handle();
  // Allocate and initialize the empty instantiations cache array instance,
  // which contains metadata as the first element and a sentinel value
  // at the start of the first entry.
  {
    const intptr_t array_size =
        static_cast<intptr_t>(TypeArguments::Cache::kHeaderSize) +
        static_cast<intptr_t>(TypeArguments::Cache::kEntrySize);
    uword address =
        heap->Allocate(thread, Array::InstanceSize(array_size), Heap::kOld);
    InitializeObjectVariant<Array>(address, kImmutableArrayCid, array_size);
    Array::initializeHandle(empty_instantiations_cache_array_,
                            static_cast<ArrayPtr>(address + kHeapObjectTag));
    empty_instantiations_cache_array_->untag()->set_length(
        Smi::New(array_size));
    // The empty cache has no occupied entries and is not a hash-based cache.
    smi = Smi::New(0);
    empty_instantiations_cache_array_->SetAt(
        TypeArguments::Cache::kMetadataIndex, smi);
    // Make the first (and only) entry unoccupied by setting its first element
    // to the sentinel value.
    smi = TypeArguments::Cache::Sentinel();
    InstantiationsCacheTable table(*empty_instantiations_cache_array_);
    table.At(0).Set<TypeArguments::Cache::kSentinelIndex>(smi);
    // The other contents of the array are immaterial.
    empty_instantiations_cache_array_->SetCanonical();
  }

  // Allocate and initialize the empty subtype test cache array instance,
  // which contains a single unoccupied entry.
  {
    const intptr_t array_size = SubtypeTestCache::kTestEntryLength;
    uword address =
        heap->Allocate(thread, Array::InstanceSize(array_size), Heap::kOld);
    InitializeObjectVariant<Array>(address, kImmutableArrayCid, array_size);
    Array::initializeHandle(empty_subtype_test_cache_array_,
                            static_cast<ArrayPtr>(address + kHeapObjectTag));
    empty_subtype_test_cache_array_->untag()->set_length(Smi::New(array_size));
    // Make the first (and only) entry unoccupied by setting its first element
    // to the null value.
    empty_subtype_test_cache_array_->SetAt(
        SubtypeTestCache::kInstanceCidOrSignature, Object::null_object());
    smi = TypeArguments::Cache::Sentinel();
    SubtypeTestCacheTable table(*empty_subtype_test_cache_array_);
    table.At(0).Set<SubtypeTestCache::kInstanceCidOrSignature>(
        Object::null_object());
    // The other contents of the array are immaterial.
    empty_subtype_test_cache_array_->SetCanonical();
  }

  // Allocate and initialize the canonical empty context scope object.
  {
    uword address =
        heap->Allocate(thread, ContextScope::InstanceSize(0), Heap::kOld);
    InitializeObject<ContextScope>(address, 0);
    ContextScope::initializeHandle(
        empty_context_scope_,
        static_cast<ContextScopePtr>(address + kHeapObjectTag));
    empty_context_scope_->StoreNonPointer(
        &empty_context_scope_->untag()->num_variables_, 0);
    empty_context_scope_->StoreNonPointer(
        &empty_context_scope_->untag()->is_implicit_, true);
    empty_context_scope_->SetCanonical();
  }

  // Allocate and initialize the canonical empty object pool object.
  {
    uword address =
        heap->Allocate(thread, ObjectPool::InstanceSize(0), Heap::kOld);
    InitializeObject<ObjectPool>(address, 0);
    ObjectPool::initializeHandle(
        empty_object_pool_,
        static_cast<ObjectPoolPtr>(address + kHeapObjectTag));
    empty_object_pool_->StoreNonPointer(&empty_object_pool_->untag()->length_,
                                        0);
    empty_object_pool_->SetCanonical();
  }

  // Allocate and initialize the empty_compressed_stackmaps instance.
  {
    const intptr_t instance_size = CompressedStackMaps::InstanceSize(0);
    uword address = heap->Allocate(thread, instance_size, Heap::kOld);
    InitializeObject<CompressedStackMaps>(address, 0);
    CompressedStackMaps::initializeHandle(
        empty_compressed_stackmaps_,
        static_cast<CompressedStackMapsPtr>(address + kHeapObjectTag));
    empty_compressed_stackmaps_->untag()->payload()->set_flags_and_size(0);
    empty_compressed_stackmaps_->SetCanonical();
  }

  // Allocate and initialize the empty_descriptors instance.
  {
    uword address =
        heap->Allocate(thread, PcDescriptors::InstanceSize(0), Heap::kOld);
    InitializeObject<PcDescriptors>(address, 0);
    PcDescriptors::initializeHandle(
        empty_descriptors_,
        static_cast<PcDescriptorsPtr>(address + kHeapObjectTag));
    empty_descriptors_->StoreNonPointer(&empty_descriptors_->untag()->length_,
                                        0);
    empty_descriptors_->SetCanonical();
  }

  // Allocate and initialize the canonical empty variable descriptor object.
  {
    uword address = heap->Allocate(thread, LocalVarDescriptors::InstanceSize(0),
                                   Heap::kOld);
    InitializeObject<LocalVarDescriptors>(address, 0);
    LocalVarDescriptors::initializeHandle(
        empty_var_descriptors_,
        static_cast<LocalVarDescriptorsPtr>(address + kHeapObjectTag));
    empty_var_descriptors_->StoreNonPointer(
        &empty_var_descriptors_->untag()->num_entries_, 0);
    empty_var_descriptors_->SetCanonical();
  }

  // Allocate and initialize the canonical empty exception handler info object.
  // The vast majority of all functions do not contain an exception handler
  // and can share this canonical descriptor.
  {
    uword address =
        heap->Allocate(thread, ExceptionHandlers::InstanceSize(0), Heap::kOld);
    InitializeObject<ExceptionHandlers>(address, 0);
    ExceptionHandlers::initializeHandle(
        empty_exception_handlers_,
        static_cast<ExceptionHandlersPtr>(address + kHeapObjectTag));
    empty_exception_handlers_->StoreNonPointer(
        &empty_exception_handlers_->untag()->packed_fields_, 0);
    empty_exception_handlers_->SetCanonical();
  }

  // Empty exception handlers for async/async* functions.
  {
    uword address =
        heap->Allocate(thread, ExceptionHandlers::InstanceSize(0), Heap::kOld);
    InitializeObject<ExceptionHandlers>(address, 0);
    ExceptionHandlers::initializeHandle(
        empty_async_exception_handlers_,
        static_cast<ExceptionHandlersPtr>(address + kHeapObjectTag));
    empty_async_exception_handlers_->StoreNonPointer(
        &empty_async_exception_handlers_->untag()->packed_fields_,
        UntaggedExceptionHandlers::AsyncHandlerBit::update(true, 0));
    empty_async_exception_handlers_->SetCanonical();
  }

  // Allocate and initialize the canonical empty type arguments object.
  {
    uword address =
        heap->Allocate(thread, TypeArguments::InstanceSize(0), Heap::kOld);
    InitializeObject<TypeArguments>(address, 0);
    TypeArguments::initializeHandle(
        empty_type_arguments_,
        static_cast<TypeArgumentsPtr>(address + kHeapObjectTag));
    empty_type_arguments_->untag()->set_length(Smi::New(0));
    empty_type_arguments_->untag()->set_hash(Smi::New(0));
    empty_type_arguments_->ComputeHash();
    empty_type_arguments_->SetCanonical();
  }

  // The VM isolate snapshot object table is initialized to an empty array
  // as we do not have any VM isolate snapshot at this time.
  *vm_isolate_snapshot_object_table_ = Object::empty_array().ptr();

  cls = Class::New<Instance, RTN::Instance>(kDynamicCid, isolate_group);
  cls.set_is_abstract();
  cls.set_num_type_arguments_unsafe(0);
  cls.set_is_allocate_finalized();
  cls.set_is_declaration_loaded();
  cls.set_is_type_finalized();
  dynamic_class_ = cls.ptr();

  cls = Class::New<Instance, RTN::Instance>(kVoidCid, isolate_group);
  cls.set_num_type_arguments_unsafe(0);
  cls.set_is_allocate_finalized();
  cls.set_is_declaration_loaded();
  cls.set_is_type_finalized();
  void_class_ = cls.ptr();

  cls = Class::New<Type, RTN::Type>(isolate_group);
  cls.set_is_allocate_finalized();
  cls.set_is_declaration_loaded();
  cls.set_is_type_finalized();

  cls = Class::New<FunctionType, RTN::FunctionType>(isolate_group);
  cls.set_is_allocate_finalized();
  cls.set_is_declaration_loaded();
  cls.set_is_type_finalized();

  cls = Class::New<RecordType, RTN::RecordType>(isolate_group);
  cls.set_is_allocate_finalized();
  cls.set_is_declaration_loaded();
  cls.set_is_type_finalized();

  cls = dynamic_class_;
  *dynamic_type_ =
      Type::New(cls, Object::null_type_arguments(), Nullability::kNullable);
  dynamic_type_->SetIsFinalized();
  dynamic_type_->ComputeHash();
  dynamic_type_->SetCanonical();

  cls = void_class_;
  *void_type_ =
      Type::New(cls, Object::null_type_arguments(), Nullability::kNullable);
  void_type_->SetIsFinalized();
  void_type_->ComputeHash();
  void_type_->SetCanonical();

  // Since TypeArguments objects are passed as function arguments, make them
  // behave as Dart instances, although they are just VM objects.
  // Note that we cannot set the super type to ObjectType, which does not live
  // in the vm isolate. See special handling in Class::SuperClass().
  cls = type_arguments_class_;
  cls.set_interfaces(Object::empty_array());
  cls.SetFields(Object::empty_array());
  cls.SetFunctions(Object::empty_array());

  cls = Class::New<Bool, RTN::Bool>(isolate_group);
  isolate_group->object_store()->set_bool_class(cls);

  *smi_illegal_cid_ = Smi::New(kIllegalCid);
  *smi_zero_ = Smi::New(0);

  String& error_str = String::Handle();
  error_str = String::New(
      "Callbacks into the Dart VM are currently prohibited. Either there are "
      "outstanding pointers from Dart_TypedDataAcquireData that have not been "
      "released with Dart_TypedDataReleaseData, or a finalizer is running.",
      Heap::kOld);
  *no_callbacks_error_ = ApiError::New(error_str, Heap::kOld);
  error_str = String::New("isolate is exiting", Heap::kOld);
  *unwind_error_ = UnwindError::New(error_str, Heap::kOld);
  error_str = String::New(
      "No api calls are allowed while unwind is in progress", Heap::kOld);
  *unwind_in_progress_error_ = UnwindError::New(error_str, Heap::kOld);
  error_str = String::New("SnapshotWriter Error", Heap::kOld);
  *snapshot_writer_error_ =
      LanguageError::New(error_str, Report::kError, Heap::kOld);
  error_str = String::New("Branch offset overflow", Heap::kOld);
  *branch_offset_error_ =
      LanguageError::New(error_str, Report::kBailout, Heap::kOld);
  error_str = String::New("Background Compilation Failed", Heap::kOld);
  *background_compilation_error_ =
      LanguageError::New(error_str, Report::kBailout, Heap::kOld);
  error_str = String::New("No debuggable code where breakpoint was requested",
                          Heap::kOld);
  *no_debuggable_code_error_ =
      LanguageError::New(error_str, Report::kError, Heap::kOld);
  error_str = String::New("Out of memory", Heap::kOld);
  *out_of_memory_error_ =
      LanguageError::New(error_str, Report::kError, Heap::kOld);
  *unhandled_oom_exception_ =
      UnhandledException::New(error_str, StackTrace::Handle(), Heap::kOld);

  // Allocate the parameter types and names for synthetic getters.
  *synthetic_getter_parameter_types_ = Array::New(1, Heap::kOld);
  synthetic_getter_parameter_types_->SetAt(0, Object::dynamic_type());
  *synthetic_getter_parameter_names_ = Array::New(1, Heap::kOld);
  // Fill in synthetic_getter_parameter_names_ later, after symbols are
  // initialized (in Object::FinalizeVMIsolate).
  // synthetic_getter_parameter_names_ object needs to be created earlier as
  // VM isolate snapshot reader references it before Object::FinalizeVMIsolate.

#if defined(DART_DYNAMIC_MODULES)
  *implicit_getter_bytecode_ =
      CreateVMInternalBytecode(KernelBytecode::kVMInternal_ImplicitGetter);

  *implicit_setter_bytecode_ =
      CreateVMInternalBytecode(KernelBytecode::kVMInternal_ImplicitSetter);

  *implicit_static_getter_bytecode_ = CreateVMInternalBytecode(
      KernelBytecode::kVMInternal_ImplicitStaticGetter);

  *implicit_static_setter_bytecode_ = CreateVMInternalBytecode(
      KernelBytecode::kVMInternal_ImplicitStaticSetter);

  *method_extractor_bytecode_ =
      CreateVMInternalBytecode(KernelBytecode::kVMInternal_MethodExtractor);

  *invoke_closure_bytecode_ =
      CreateVMInternalBytecode(KernelBytecode::kVMInternal_InvokeClosure);

  *invoke_field_bytecode_ =
      CreateVMInternalBytecode(KernelBytecode::kVMInternal_InvokeField);

  *nsm_dispatcher_bytecode_ = CreateVMInternalBytecode(
      KernelBytecode::kVMInternal_NoSuchMethodDispatcher);

  *dynamic_invocation_forwarder_bytecode_ = CreateVMInternalBytecode(
      KernelBytecode::kVMInternal_ForwardDynamicInvocation);

  *implicit_static_closure_bytecode_ = CreateVMInternalBytecode(
      KernelBytecode::kVMInternal_ImplicitStaticClosure);

  *implicit_instance_closure_bytecode_ = CreateVMInternalBytecode(
      KernelBytecode::kVMInternal_ImplicitInstanceClosure);

  *implicit_constructor_closure_bytecode_ = CreateVMInternalBytecode(
      KernelBytecode::kVMInternal_ImplicitConstructorClosure);
#endif  // defined(DART_DYNAMIC_MODULES)

  *uninitialized_index_ =
      TypedData::New(kTypedDataUint32ArrayCid,
                     LinkedHashBase::kUninitializedIndexSize, Heap::kOld);
  *uninitialized_data_ = Array::New(0, Heap::kOld);

  // Some thread fields need to be reinitialized as null constants have not been
  // initialized until now.
  thread->ClearStickyError();

  ASSERT(!null_object_->IsSmi());
  ASSERT(!null_class_->IsSmi());
  ASSERT(null_class_->IsClass());
  ASSERT(!null_array_->IsSmi());
  ASSERT(null_array_->IsArray());
  ASSERT(!null_string_->IsSmi());
  ASSERT(null_string_->IsString());
  ASSERT(!null_instance_->IsSmi());
  ASSERT(null_instance_->IsInstance());
  ASSERT(!null_function_->IsSmi());
  ASSERT(null_function_->IsFunction());
  ASSERT(!null_function_type_->IsSmi());
  ASSERT(null_function_type_->IsFunctionType());
  ASSERT(!null_record_type_->IsSmi());
  ASSERT(null_record_type_->IsRecordType());
  ASSERT(!null_type_arguments_->IsSmi());
  ASSERT(null_type_arguments_->IsTypeArguments());
  ASSERT(!null_compressed_stackmaps_->IsSmi());
  ASSERT(null_compressed_stackmaps_->IsCompressedStackMaps());
  ASSERT(!empty_array_->IsSmi());
  ASSERT(empty_array_->IsArray());
  ASSERT(!empty_instantiations_cache_array_->IsSmi());
  ASSERT(empty_instantiations_cache_array_->IsArray());
  ASSERT(!empty_subtype_test_cache_array_->IsSmi());
  ASSERT(empty_subtype_test_cache_array_->IsArray());
  ASSERT(!empty_type_arguments_->IsSmi());
  ASSERT(empty_type_arguments_->IsTypeArguments());
  ASSERT(!empty_context_scope_->IsSmi());
  ASSERT(empty_context_scope_->IsContextScope());
  ASSERT(!empty_compressed_stackmaps_->IsSmi());
  ASSERT(empty_compressed_stackmaps_->IsCompressedStackMaps());
  ASSERT(!empty_descriptors_->IsSmi());
  ASSERT(empty_descriptors_->IsPcDescriptors());
  ASSERT(!empty_var_descriptors_->IsSmi());
  ASSERT(empty_var_descriptors_->IsLocalVarDescriptors());
  ASSERT(!empty_exception_handlers_->IsSmi());
  ASSERT(empty_exception_handlers_->IsExceptionHandlers());
  ASSERT(!empty_async_exception_handlers_->IsSmi());
  ASSERT(empty_async_exception_handlers_->IsExceptionHandlers());
  ASSERT(!sentinel_->IsSmi());
  ASSERT(sentinel_->IsSentinel());
  ASSERT(!unknown_constant_->IsSmi());
  ASSERT(unknown_constant_->IsSentinel());
  ASSERT(!non_constant_->IsSmi());
  ASSERT(non_constant_->IsSentinel());
  ASSERT(!optimized_out_->IsSmi());
  ASSERT(optimized_out_->IsSentinel());
  ASSERT(!bool_true_->IsSmi());
  ASSERT(bool_true_->IsBool());
  ASSERT(!bool_false_->IsSmi());
  ASSERT(bool_false_->IsBool());
  ASSERT(smi_illegal_cid_->IsSmi());
  ASSERT(smi_zero_->IsSmi());
  ASSERT(!no_callbacks_error_->IsSmi());
  ASSERT(no_callbacks_error_->IsApiError());
  ASSERT(!unwind_error_->IsSmi());
  ASSERT(unwind_error_->IsUnwindError());
  ASSERT(!unwind_in_progress_error_->IsSmi());
  ASSERT(unwind_in_progress_error_->IsUnwindError());
  ASSERT(!snapshot_writer_error_->IsSmi());
  ASSERT(snapshot_writer_error_->IsLanguageError());
  ASSERT(!branch_offset_error_->IsSmi());
  ASSERT(branch_offset_error_->IsLanguageError());
  ASSERT(!background_compilation_error_->IsSmi());
  ASSERT(background_compilation_error_->IsLanguageError());
  ASSERT(!out_of_memory_error_->IsSmi());
  ASSERT(out_of_memory_error_->IsLanguageError());
  ASSERT(!unhandled_oom_exception_->IsSmi());
  ASSERT(unhandled_oom_exception_->IsUnhandledException());
  ASSERT(!vm_isolate_snapshot_object_table_->IsSmi());
  ASSERT(vm_isolate_snapshot_object_table_->IsArray());
  ASSERT(!synthetic_getter_parameter_types_->IsSmi());
  ASSERT(synthetic_getter_parameter_types_->IsArray());
  ASSERT(!synthetic_getter_parameter_names_->IsSmi());
  ASSERT(synthetic_getter_parameter_names_->IsArray());
  ASSERT(!implicit_getter_bytecode_->IsSmi());
  ASSERT(implicit_getter_bytecode_->IsBytecode());
  ASSERT(!implicit_setter_bytecode_->IsSmi());
  ASSERT(implicit_setter_bytecode_->IsBytecode());
  ASSERT(!implicit_static_getter_bytecode_->IsSmi());
  ASSERT(implicit_static_getter_bytecode_->IsBytecode());
  ASSERT(!implicit_static_setter_bytecode_->IsSmi());
  ASSERT(implicit_static_setter_bytecode_->IsBytecode());
  ASSERT(!method_extractor_bytecode_->IsSmi());
  ASSERT(method_extractor_bytecode_->IsBytecode());
  ASSERT(!invoke_closure_bytecode_->IsSmi());
  ASSERT(invoke_closure_bytecode_->IsBytecode());
  ASSERT(!invoke_field_bytecode_->IsSmi());
  ASSERT(invoke_field_bytecode_->IsBytecode());
  ASSERT(!nsm_dispatcher_bytecode_->IsSmi());
  ASSERT(nsm_dispatcher_bytecode_->IsBytecode());
  ASSERT(!dynamic_invocation_forwarder_bytecode_->IsSmi());
  ASSERT(dynamic_invocation_forwarder_bytecode_->IsBytecode());
  ASSERT(!implicit_static_closure_bytecode_->IsSmi());
  ASSERT(implicit_static_closure_bytecode_->IsBytecode());
  ASSERT(!implicit_instance_closure_bytecode_->IsSmi());
  ASSERT(implicit_instance_closure_bytecode_->IsBytecode());
  ASSERT(!implicit_constructor_closure_bytecode_->IsSmi());
  ASSERT(implicit_constructor_closure_bytecode_->IsBytecode());
  ASSERT(!uninitialized_index_->IsSmi());
  ASSERT(uninitialized_index_->IsTypedData());
  ASSERT(!uninitialized_data_->IsSmi());
  ASSERT(uninitialized_data_->IsArray());
}

void Object::FinishInit(IsolateGroup* isolate_group) {
  // The type testing stubs we initialize in AbstractType objects for the
  // canonical type of kDynamicCid/kVoidCid need to be set in this
  // method, which is called after StubCode::InitOnce().
  Code& code = Code::Handle();

  code = TypeTestingStubGenerator::DefaultCodeForType(*dynamic_type_);
  dynamic_type_->InitializeTypeTestingStubNonAtomic(code);

  code = TypeTestingStubGenerator::DefaultCodeForType(*void_type_);
  void_type_->InitializeTypeTestingStubNonAtomic(code);
}

void Object::Cleanup() {
  null_ = static_cast<ObjectPtr>(RAW_NULL);
  true_ = static_cast<BoolPtr>(RAW_NULL);
  false_ = static_cast<BoolPtr>(RAW_NULL);
  class_class_ = static_cast<ClassPtr>(RAW_NULL);
  dynamic_class_ = static_cast<ClassPtr>(RAW_NULL);
  void_class_ = static_cast<ClassPtr>(RAW_NULL);
  type_parameters_class_ = static_cast<ClassPtr>(RAW_NULL);
  type_arguments_class_ = static_cast<ClassPtr>(RAW_NULL);
  patch_class_class_ = static_cast<ClassPtr>(RAW_NULL);
  function_class_ = static_cast<ClassPtr>(RAW_NULL);
  closure_data_class_ = static_cast<ClassPtr>(RAW_NULL);
  ffi_trampoline_data_class_ = static_cast<ClassPtr>(RAW_NULL);
  field_class_ = static_cast<ClassPtr>(RAW_NULL);
  script_class_ = static_cast<ClassPtr>(RAW_NULL);
  library_class_ = static_cast<ClassPtr>(RAW_NULL);
  namespace_class_ = static_cast<ClassPtr>(RAW_NULL);
  kernel_program_info_class_ = static_cast<ClassPtr>(RAW_NULL);
  code_class_ = static_cast<ClassPtr>(RAW_NULL);
  instructions_class_ = static_cast<ClassPtr>(RAW_NULL);
  instructions_section_class_ = static_cast<ClassPtr>(RAW_NULL);
  instructions_table_class_ = static_cast<ClassPtr>(RAW_NULL);
  object_pool_class_ = static_cast<ClassPtr>(RAW_NULL);
  pc_descriptors_class_ = static_cast<ClassPtr>(RAW_NULL);
  code_source_map_class_ = static_cast<ClassPtr>(RAW_NULL);
  compressed_stackmaps_class_ = static_cast<ClassPtr>(RAW_NULL);
  var_descriptors_class_ = static_cast<ClassPtr>(RAW_NULL);
  exception_handlers_class_ = static_cast<ClassPtr>(RAW_NULL);
  context_class_ = static_cast<ClassPtr>(RAW_NULL);
  context_scope_class_ = static_cast<ClassPtr>(RAW_NULL);
  bytecode_class_ = static_cast<ClassPtr>(RAW_NULL);
  singletargetcache_class_ = static_cast<ClassPtr>(RAW_NULL);
  unlinkedcall_class_ = static_cast<ClassPtr>(RAW_NULL);
  monomorphicsmiablecall_class_ = static_cast<ClassPtr>(RAW_NULL);
  icdata_class_ = static_cast<ClassPtr>(RAW_NULL);
  megamorphic_cache_class_ = static_cast<ClassPtr>(RAW_NULL);
  subtypetestcache_class_ = static_cast<ClassPtr>(RAW_NULL);
  loadingunit_class_ = static_cast<ClassPtr>(RAW_NULL);
  api_error_class_ = static_cast<ClassPtr>(RAW_NULL);
  language_error_class_ = static_cast<ClassPtr>(RAW_NULL);
  unhandled_exception_class_ = static_cast<ClassPtr>(RAW_NULL);
  unwind_error_class_ = static_cast<ClassPtr>(RAW_NULL);
}

// An object visitor which will mark all visited objects. This is used to
// premark all objects in the vm_isolate_ heap.  Also precalculates hash
// codes so that we can get the identity hash code of objects in the read-
// only VM isolate.
class FinalizeVMIsolateVisitor : public ObjectVisitor {
 public:
  FinalizeVMIsolateVisitor()
#if defined(HASH_IN_OBJECT_HEADER)
      : counter_(1337)
#endif
  {
  }

  void VisitObject(ObjectPtr obj) {
    // Free list elements should never be marked.
    ASSERT(!obj->untag()->IsMarked());
    // No forwarding corpses in the VM isolate.
    ASSERT(!obj->IsForwardingCorpse());
    if (!obj->IsFreeListElement()) {
      obj->untag()->SetMarkBitUnsynchronized();
      Object::FinalizeReadOnlyObject(obj);
#if defined(HASH_IN_OBJECT_HEADER)
      // These objects end up in the read-only VM isolate which is shared
      // between isolates, so we have to prepopulate them with identity hash
      // codes, since we can't add hash codes later.
      if (Object::GetCachedHash(obj) == 0) {
        // Some classes have identity hash codes that depend on their contents,
        // not per object.
        ASSERT(!obj->IsStringInstance());
        if (obj == Object::null()) {
          Object::SetCachedHashIfNotSet(obj, kNullIdentityHash);
        } else if (obj == Object::bool_true().ptr()) {
          Object::SetCachedHashIfNotSet(obj, kTrueIdentityHash);
        } else if (obj == Object::bool_false().ptr()) {
          Object::SetCachedHashIfNotSet(obj, kFalseIdentityHash);
        } else if (!obj->IsMint() && !obj->IsDouble()) {
          counter_ += 2011;  // The year Dart was announced and a prime.
          counter_ &= 0x3fffffff;
          if (counter_ == 0) counter_++;
          Object::SetCachedHashIfNotSet(obj, counter_);
        }
      }
#endif
#if !defined(DART_PRECOMPILED_RUNTIME)
      if (obj->IsClass()) {
        // Won't be able to update read-only VM isolate classes if implementors
        // are discovered later. We use kVoidCid instead of kDynamicCid here to
        // be able to distinguish read-only VM isolate classes during reload.
        // See ProgramReloadContext::RestoreClassHierarchyInvariants.
        static_cast<ClassPtr>(obj)->untag()->implementor_cid_ = kVoidCid;
      }
#endif
    }
  }

 private:
#if defined(HASH_IN_OBJECT_HEADER)
  int32_t counter_;
#endif
};

#define SET_CLASS_NAME(class_name, name)                                       \
  cls = class_name##_class();                                                  \
  cls.set_name(Symbols::name());

void Object::FinalizeVMIsolate(IsolateGroup* isolate_group) {
  // Should only be run by the vm isolate.
  ASSERT(isolate_group == Dart::vm_isolate_group());

  // Finish initialization of synthetic_getter_parameter_names_ which was
  // Started in Object::InitOnce()
  synthetic_getter_parameter_names_->SetAt(0, Symbols::This());

  // Set up names for all VM singleton classes.
  Class& cls = Class::Handle();

  SET_CLASS_NAME(class, Class);
  SET_CLASS_NAME(dynamic, Dynamic);
  SET_CLASS_NAME(void, Void);
  SET_CLASS_NAME(type_parameters, TypeParameters);
  SET_CLASS_NAME(type_arguments, TypeArguments);
  SET_CLASS_NAME(patch_class, PatchClass);
  SET_CLASS_NAME(function, Function);
  SET_CLASS_NAME(closure_data, ClosureData);
  SET_CLASS_NAME(ffi_trampoline_data, FfiTrampolineData);
  SET_CLASS_NAME(field, Field);
  SET_CLASS_NAME(script, Script);
  SET_CLASS_NAME(library, LibraryClass);
  SET_CLASS_NAME(namespace, Namespace);
  SET_CLASS_NAME(kernel_program_info, KernelProgramInfo);
  SET_CLASS_NAME(weak_serialization_reference, WeakSerializationReference);
  SET_CLASS_NAME(weak_array, WeakArray);
  SET_CLASS_NAME(code, Code);
  SET_CLASS_NAME(instructions, Instructions);
  SET_CLASS_NAME(instructions_section, InstructionsSection);
  SET_CLASS_NAME(instructions_table, InstructionsTable);
  SET_CLASS_NAME(object_pool, ObjectPool);
  SET_CLASS_NAME(code_source_map, CodeSourceMap);
  SET_CLASS_NAME(pc_descriptors, PcDescriptors);
  SET_CLASS_NAME(compressed_stackmaps, CompressedStackMaps);
  SET_CLASS_NAME(var_descriptors, LocalVarDescriptors);
  SET_CLASS_NAME(exception_handlers, ExceptionHandlers);
  SET_CLASS_NAME(context, Context);
  SET_CLASS_NAME(context_scope, ContextScope);
  SET_CLASS_NAME(bytecode, Bytecode);
  SET_CLASS_NAME(sentinel, Sentinel);
  SET_CLASS_NAME(singletargetcache, SingleTargetCache);
  SET_CLASS_NAME(unlinkedcall, UnlinkedCall);
  SET_CLASS_NAME(monomorphicsmiablecall, MonomorphicSmiableCall);
  SET_CLASS_NAME(icdata, ICData);
  SET_CLASS_NAME(megamorphic_cache, MegamorphicCache);
  SET_CLASS_NAME(subtypetestcache, SubtypeTestCache);
  SET_CLASS_NAME(loadingunit, LoadingUnit);
  SET_CLASS_NAME(api_error, ApiError);
  SET_CLASS_NAME(language_error, LanguageError);
  SET_CLASS_NAME(unhandled_exception, UnhandledException);
  SET_CLASS_NAME(unwind_error, UnwindError);

  // Set up names for classes which are also pre-allocated in the vm isolate.
  cls = isolate_group->object_store()->array_class();
  cls.set_name(Symbols::_List());
  cls = isolate_group->object_store()->one_byte_string_class();
  cls.set_name(Symbols::OneByteString());
  cls = isolate_group->object_store()->never_class();
  cls.set_name(Symbols::Never());

  // Set up names for the pseudo-classes for free list elements and forwarding
  // corpses. Mainly this makes VM debugging easier.
  cls = isolate_group->class_table()->At(kFreeListElement);
  cls.set_name(Symbols::FreeListElement());
  cls = isolate_group->class_table()->At(kForwardingCorpse);
  cls.set_name(Symbols::ForwardingCorpse());

#if defined(DART_PRECOMPILER)
  const auto& function =
      Function::Handle(StubCode::UnknownDartCode().function());
  function.set_name(Symbols::OptimizedOut());
#endif  // defined(DART_PRECOMPILER)

  {
    ASSERT(isolate_group == Dart::vm_isolate_group());
    Thread* thread = Thread::Current();
    WritableVMIsolateScope scope(thread);
    HeapIterationScope iteration(thread);
    FinalizeVMIsolateVisitor premarker;
    ASSERT(isolate_group->heap()->UsedInWords(Heap::kNew) == 0);
    iteration.IterateOldObjectsNoImagePages(&premarker);
    // Make the VM isolate read-only again after setting all objects as marked.
    // Note objects in image pages are already pre-marked.
  }
}

void Object::FinalizeReadOnlyObject(ObjectPtr object) {
  NoSafepointScope no_safepoint;
  intptr_t cid = object->GetClassIdOfHeapObject();
  if (cid == kOneByteStringCid) {
    OneByteStringPtr str = static_cast<OneByteStringPtr>(object);
    if (String::GetCachedHash(str) == 0) {
      intptr_t hash = String::Hash(str);
      String::SetCachedHashIfNotSet(str, hash);
    }
    intptr_t size = OneByteString::UnroundedSize(str);
    ASSERT(size <= str->untag()->HeapSize());
    memset(reinterpret_cast<void*>(UntaggedObject::ToAddr(str) + size), 0,
           str->untag()->HeapSize() - size);
  } else if (cid == kTwoByteStringCid) {
    TwoByteStringPtr str = static_cast<TwoByteStringPtr>(object);
    if (String::GetCachedHash(str) == 0) {
      intptr_t hash = String::Hash(str);
      String::SetCachedHashIfNotSet(str, hash);
    }
    ASSERT(String::GetCachedHash(str) != 0);
    intptr_t size = TwoByteString::UnroundedSize(str);
    ASSERT(size <= str->untag()->HeapSize());
    memset(reinterpret_cast<void*>(UntaggedObject::ToAddr(str) + size), 0,
           str->untag()->HeapSize() - size);
  } else if (cid == kCodeSourceMapCid) {
    CodeSourceMapPtr map = CodeSourceMap::RawCast(object);
    intptr_t size = CodeSourceMap::UnroundedSize(map);
    ASSERT(size <= map->untag()->HeapSize());
    memset(reinterpret_cast<void*>(UntaggedObject::ToAddr(map) + size), 0,
           map->untag()->HeapSize() - size);
  } else if (cid == kCompressedStackMapsCid) {
    CompressedStackMapsPtr maps = CompressedStackMaps::RawCast(object);
    intptr_t size = CompressedStackMaps::UnroundedSize(maps);
    ASSERT(size <= maps->untag()->HeapSize());
    memset(reinterpret_cast<void*>(UntaggedObject::ToAddr(maps) + size), 0,
           maps->untag()->HeapSize() - size);
  } else if (cid == kPcDescriptorsCid) {
    PcDescriptorsPtr desc = PcDescriptors::RawCast(object);
    intptr_t size = PcDescriptors::UnroundedSize(desc);
    ASSERT(size <= desc->untag()->HeapSize());
    memset(reinterpret_cast<void*>(UntaggedObject::ToAddr(desc) + size), 0,
           desc->untag()->HeapSize() - size);
  }
}

void Object::set_vm_isolate_snapshot_object_table(const Array& table) {
  ASSERT(Isolate::Current() == Dart::vm_isolate());
  *vm_isolate_snapshot_object_table_ = table.ptr();
}

// Make unused space in an object whose type has been transformed safe
// for traversing during GC.
// The unused part of the transformed object is marked as a FreeListElement
// object that is not inserted into to the freelist.
void Object::MakeUnusedSpaceTraversable(const Object& obj,
                                        intptr_t original_size,
                                        intptr_t used_size) {
  ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0);
  ASSERT(!obj.IsNull());
  ASSERT(original_size >= used_size);
  if (original_size > used_size) {
    intptr_t leftover_size = original_size - used_size;
    uword addr = UntaggedObject::ToAddr(obj.ptr()) + used_size;
    if (obj.ptr()->IsNewObject()) {
      FreeListElement::AsElementNew(addr, leftover_size);
    } else {
      FreeListElement::AsElement(addr, leftover_size);
    }
    // On architectures with a relaxed memory model, the concurrent marker may
    // observe the write of the filler object's header before observing the
    // new array length, and so treat it as a pointer. Ensure it is a Smi so
    // the marker won't dereference it.
    ASSERT((*reinterpret_cast<uword*>(addr) & kSmiTagMask) == kSmiTag);
    ASSERT((*reinterpret_cast<uword*>(addr + kWordSize) & kSmiTagMask) ==
           kSmiTag);
  }
}

void Object::VerifyBuiltinVtables() {
#if defined(DEBUG)
  ASSERT(builtin_vtables_[kIllegalCid] == 0);
  ASSERT(builtin_vtables_[kFreeListElement] == 0);
  ASSERT(builtin_vtables_[kForwardingCorpse] == 0);
  ClassTable* table = IsolateGroup::Current()->class_table();
  for (intptr_t cid = kObjectCid; cid < kNumPredefinedCids; cid++) {
    if (table->HasValidClassAt(cid)) {
      ASSERT(builtin_vtables_[cid] != 0);
    }
  }
#endif
}

void Object::RegisterClass(const Class& cls,
                           const String& name,
                           const Library& lib) {
  ASSERT(name.Length() > 0);
  ASSERT(name.CharAt(0) != '_');
  cls.set_name(name);
  lib.AddClass(cls);
}

void Object::RegisterPrivateClass(const Class& cls,
                                  const String& public_class_name,
                                  const Library& lib) {
  ASSERT(public_class_name.Length() > 0);
  ASSERT(public_class_name.CharAt(0) == '_');
  String& str = String::Handle();
  str = lib.PrivateName(public_class_name);
  cls.set_name(str);
  lib.AddClass(cls);
}

// Initialize a new isolate from source or from a snapshot.
//
// There are three possibilities:
//   1. Running a Kernel binary.  This function will bootstrap from the KERNEL
//      file.
//   2. There is no vm snapshot.  This function will bootstrap from source.
//   3. There is a vm snapshot.  The caller should initialize from the snapshot.
//
// A non-null kernel argument indicates (1).
// A nullptr kernel indicates (2) or (3).
ErrorPtr Object::Init(IsolateGroup* isolate_group,
                      const uint8_t* kernel_buffer,
                      intptr_t kernel_buffer_size) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  ASSERT(isolate_group == thread->isolate_group());
  TIMELINE_DURATION(thread, Isolate, "Object::Init");

#if defined(DART_PRECOMPILED_RUNTIME)
  const bool bootstrapping = false;
#else
  const bool is_kernel = (kernel_buffer != nullptr);
  const bool bootstrapping =
      (Dart::vm_snapshot_kind() == Snapshot::kNone) || is_kernel;
#endif  // defined(DART_PRECOMPILED_RUNTIME).

  if (bootstrapping) {
#if !defined(DART_PRECOMPILED_RUNTIME)
    // Object::Init version when we are bootstrapping from source or from a
    // Kernel binary.
    // This will initialize isolate group object_store, shared by all isolates
    // running in the isolate group.
    ObjectStore* object_store = isolate_group->object_store();
    SafepointWriteRwLocker ml(thread, isolate_group->program_lock());

    Class& cls = Class::Handle(zone);
    Type& type = Type::Handle(zone);
    Array& array = Array::Handle(zone);
    WeakArray& weak_array = WeakArray::Handle(zone);
    Library& lib = Library::Handle(zone);
    TypeArguments& type_args = TypeArguments::Handle(zone);

    // All RawArray fields will be initialized to an empty array, therefore
    // initialize array class first.
    cls = Class::New<Array, RTN::Array>(isolate_group);
    ASSERT(object_store->array_class() == Class::null());
    object_store->set_array_class(cls);

    // VM classes that are parameterized (Array, ImmutableArray,
    // GrowableObjectArray, Map, ConstMap,
    // Set, ConstSet) are also pre-finalized, so
    // CalculateFieldOffsets() is not called, so we need to set the offset
    // of their type_arguments_ field, which is explicitly
    // declared in their respective Raw* classes.
    cls.set_type_arguments_field_offset(Array::type_arguments_offset(),
                                        RTN::Array::type_arguments_offset());
    cls.set_num_type_arguments_unsafe(1);

    // Set up the growable object array class (Has to be done after the array
    // class is setup as one of its field is an array object).
    cls = Class::New<GrowableObjectArray, RTN::GrowableObjectArray>(
        isolate_group);
    object_store->set_growable_object_array_class(cls);
    cls.set_type_arguments_field_offset(
        GrowableObjectArray::type_arguments_offset(),
        RTN::GrowableObjectArray::type_arguments_offset());
    cls.set_num_type_arguments_unsafe(1);

    // Initialize hash set for regexp_table_.
    const intptr_t kInitialCanonicalRegExpSize = 4;
    weak_array = HashTables::New<CanonicalRegExpSet>(
        kInitialCanonicalRegExpSize, Heap::kOld);
    object_store->set_regexp_table(weak_array);

    // Initialize hash set for canonical types.
    const intptr_t kInitialCanonicalTypeSize = 16;
    array = HashTables::New<CanonicalTypeSet>(kInitialCanonicalTypeSize,
                                              Heap::kOld);
    object_store->set_canonical_types(array);

    // Initialize hash set for canonical function types.
    const intptr_t kInitialCanonicalFunctionTypeSize = 16;
    array = HashTables::New<CanonicalFunctionTypeSet>(
        kInitialCanonicalFunctionTypeSize, Heap::kOld);
    object_store->set_canonical_function_types(array);

    // Initialize hash set for canonical record types.
    const intptr_t kInitialCanonicalRecordTypeSize = 16;
    array = HashTables::New<CanonicalRecordTypeSet>(
        kInitialCanonicalRecordTypeSize, Heap::kOld);
    object_store->set_canonical_record_types(array);

    // Initialize hash set for canonical type parameters.
    const intptr_t kInitialCanonicalTypeParameterSize = 4;
    array = HashTables::New<CanonicalTypeParameterSet>(
        kInitialCanonicalTypeParameterSize, Heap::kOld);
    object_store->set_canonical_type_parameters(array);

    // Initialize hash set for canonical_type_arguments_.
    const intptr_t kInitialCanonicalTypeArgumentsSize = 4;
    array = HashTables::New<CanonicalTypeArgumentsSet>(
        kInitialCanonicalTypeArgumentsSize, Heap::kOld);
    object_store->set_canonical_type_arguments(array);

    // Setup type class early in the process.
    const Class& type_cls =
        Class::Handle(zone, Class::New<Type, RTN::Type>(isolate_group));
    const Class& function_type_cls = Class::Handle(
        zone, Class::New<FunctionType, RTN::FunctionType>(isolate_group));
    const Class& record_type_cls = Class::Handle(
        zone, Class::New<RecordType, RTN::RecordType>(isolate_group));
    const Class& type_parameter_cls = Class::Handle(
        zone, Class::New<TypeParameter, RTN::TypeParameter>(isolate_group));
    const Class& library_prefix_cls = Class::Handle(
        zone, Class::New<LibraryPrefix, RTN::LibraryPrefix>(isolate_group));

    // Pre-allocate the OneByteString class needed by the symbol table.
    cls = Class::NewStringClass(kOneByteStringCid, isolate_group);
    object_store->set_one_byte_string_class(cls);

    // Pre-allocate the TwoByteString class needed by the symbol table.
    cls = Class::NewStringClass(kTwoByteStringCid, isolate_group);
    object_store->set_two_byte_string_class(cls);

    // Setup the symbol table for the symbols created in the isolate.
    Symbols::SetupSymbolTable(isolate_group);

    // Set up the libraries array before initializing the core library.
    const GrowableObjectArray& libraries =
        GrowableObjectArray::Handle(zone, GrowableObjectArray::New(Heap::kOld));
    object_store->set_libraries(libraries);

    // Pre-register the core library.
    Library::InitCoreLibrary(isolate_group);

    // Basic infrastructure has been setup, initialize the class dictionary.
    const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
    ASSERT(!core_lib.IsNull());

    const GrowableObjectArray& pending_classes =
        GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
    object_store->set_pending_classes(pending_classes);

    // Now that the symbol table is initialized and that the core dictionary as
    // well as the core implementation dictionary have been setup, preallocate
    // remaining classes and register them by name in the dictionaries.
    String& name = String::Handle(zone);
    cls = object_store->array_class();  // Was allocated above.
    RegisterPrivateClass(cls, Symbols::_List(), core_lib);
    pending_classes.Add(cls);
    // We cannot use NewNonParameterizedType(), because Array is
    // parameterized.  Warning: class _List has not been patched yet. Its
    // declared number of type parameters is still 0. It will become 1 after
    // patching. The array type allocated below represents the raw type _List
    // and not _List<E> as we could expect. Use with caution.
    type = Type::New(Class::Handle(zone, cls.ptr()),
                     Object::null_type_arguments(), Nullability::kNonNullable);
    type.SetIsFinalized();
    type ^= type.Canonicalize(thread);
    object_store->set_array_type(type);

    cls = object_store->growable_object_array_class();  // Was allocated above.
    RegisterPrivateClass(cls, Symbols::_GrowableList(), core_lib);
    pending_classes.Add(cls);

    cls = Class::New<Array, RTN::Array>(kImmutableArrayCid, isolate_group);
    object_store->set_immutable_array_class(cls);
    cls.set_type_arguments_field_offset(Array::type_arguments_offset(),
                                        RTN::Array::type_arguments_offset());
    cls.set_num_type_arguments_unsafe(1);
    ASSERT(object_store->immutable_array_class() !=
           object_store->array_class());
    cls.set_is_prefinalized();
    RegisterPrivateClass(cls, Symbols::_ImmutableList(), core_lib);
    pending_classes.Add(cls);

    cls = object_store->one_byte_string_class();  // Was allocated above.
    RegisterPrivateClass(cls, Symbols::OneByteString(), core_lib);
    pending_classes.Add(cls);

    cls = object_store->two_byte_string_class();  // Was allocated above.
    RegisterPrivateClass(cls, Symbols::TwoByteString(), core_lib);
    pending_classes.Add(cls);

    // Pre-register the isolate library so the native class implementations can
    // be hooked up before compiling it.
    Library& isolate_lib = Library::Handle(
        zone, Library::LookupLibrary(thread, Symbols::DartIsolate()));
    if (isolate_lib.IsNull()) {
      isolate_lib = Library::NewLibraryHelper(Symbols::DartIsolate(), true);
      isolate_lib.SetLoadRequested();
      isolate_lib.Register(thread);
    }
    object_store->set_bootstrap_library(ObjectStore::kIsolate, isolate_lib);
    ASSERT(!isolate_lib.IsNull());
    ASSERT(isolate_lib.ptr() == Library::IsolateLibrary());

    cls = Class::New<Capability, RTN::Capability>(isolate_group);
    RegisterPrivateClass(cls, Symbols::_Capability(), isolate_lib);
    pending_classes.Add(cls);

    cls = Class::New<ReceivePort, RTN::ReceivePort>(isolate_group);
    RegisterPrivateClass(cls, Symbols::_RawReceivePort(), isolate_lib);
    pending_classes.Add(cls);

    cls = Class::New<SendPort, RTN::SendPort>(isolate_group);
    RegisterPrivateClass(cls, Symbols::_SendPort(), isolate_lib);
    pending_classes.Add(cls);

    cls = Class::New<TransferableTypedData, RTN::TransferableTypedData>(
        isolate_group);
    RegisterPrivateClass(cls, Symbols::_TransferableTypedDataImpl(),
                         isolate_lib);
    pending_classes.Add(cls);

    const Class& stacktrace_cls = Class::Handle(
        zone, Class::New<StackTrace, RTN::StackTrace>(isolate_group));
    RegisterPrivateClass(stacktrace_cls, Symbols::_StackTrace(), core_lib);
    pending_classes.Add(stacktrace_cls);
    // Super type set below, after Object is allocated.

    cls = Class::New<RegExp, RTN::RegExp>(isolate_group);
    RegisterPrivateClass(cls, Symbols::_RegExp(), core_lib);
    pending_classes.Add(cls);

    // Initialize the base interfaces used by the core VM classes.

    // Allocate and initialize the pre-allocated classes in the core library.
    // The script and token index of these pre-allocated classes is set up when
    // the corelib script is compiled.
    cls = Class::New<Instance, RTN::Instance>(kInstanceCid, isolate_group);
    object_store->set_object_class(cls);
    cls.set_name(Symbols::Object());
    cls.set_num_type_arguments_unsafe(0);
    cls.set_is_prefinalized();
    cls.set_is_const();
    core_lib.AddClass(cls);
    pending_classes.Add(cls);
    type = Type::NewNonParameterizedType(cls);
    ASSERT(type.IsCanonical());
    object_store->set_object_type(type);
    type = type.ToNullability(Nullability::kNonNullable, Heap::kOld);
    ASSERT(type.IsCanonical());
    object_store->set_non_nullable_object_type(type);
    type = type.ToNullability(Nullability::kNullable, Heap::kOld);
    ASSERT(type.IsCanonical());
    object_store->set_nullable_object_type(type);

    cls = Class::New<Bool, RTN::Bool>(isolate_group);
    object_store->set_bool_class(cls);
    RegisterClass(cls, Symbols::Bool(), core_lib);
    pending_classes.Add(cls);

    cls = Class::New<Instance, RTN::Instance>(kNullCid, isolate_group);
    object_store->set_null_class(cls);
    cls.set_num_type_arguments_unsafe(0);
    cls.set_is_prefinalized();
    RegisterClass(cls, Symbols::Null(), core_lib);
    pending_classes.Add(cls);

    cls = Class::New<Instance, RTN::Instance>(kNeverCid, isolate_group);
    cls.set_num_type_arguments_unsafe(0);
    cls.set_is_allocate_finalized();
    cls.set_is_declaration_loaded();
    cls.set_is_type_finalized();
    cls.set_name(Symbols::Never());
    object_store->set_never_class(cls);

    ASSERT(!library_prefix_cls.IsNull());
    RegisterPrivateClass(library_prefix_cls, Symbols::_LibraryPrefix(),
                         core_lib);
    pending_classes.Add(library_prefix_cls);

    RegisterPrivateClass(type_cls, Symbols::_Type(), core_lib);
    pending_classes.Add(type_cls);

    RegisterPrivateClass(function_type_cls, Symbols::_FunctionType(), core_lib);
    pending_classes.Add(function_type_cls);

    RegisterPrivateClass(record_type_cls, Symbols::_RecordType(), core_lib);
    pending_classes.Add(record_type_cls);

    RegisterPrivateClass(type_parameter_cls, Symbols::_TypeParameter(),
                         core_lib);
    pending_classes.Add(type_parameter_cls);

    cls = Class::New<Integer, RTN::Integer>(isolate_group);
    object_store->set_integer_implementation_class(cls);
    RegisterPrivateClass(cls, Symbols::_IntegerImplementation(), core_lib);
    pending_classes.Add(cls);

    cls = Class::New<Smi, RTN::Smi>(isolate_group);
    object_store->set_smi_class(cls);
    RegisterPrivateClass(cls, Symbols::_Smi(), core_lib);
    pending_classes.Add(cls);

    cls = Class::New<Mint, RTN::Mint>(isolate_group);
    object_store->set_mint_class(cls);
    RegisterPrivateClass(cls, Symbols::_Mint(), core_lib);
    pending_classes.Add(cls);

    cls = Class::New<Double, RTN::Double>(isolate_group);
    object_store->set_double_class(cls);
    RegisterPrivateClass(cls, Symbols::_Double(), core_lib);
    pending_classes.Add(cls);

    // Class that represents the Dart class _Closure and C++ class Closure.
    cls = Class::New<Closure, RTN::Closure>(isolate_group);
    object_store->set_closure_class(cls);
    RegisterPrivateClass(cls, Symbols::_Closure(), core_lib);
    pending_classes.Add(cls);

    cls = Class::New<Record, RTN::Record>(isolate_group);
    RegisterPrivateClass(cls, Symbols::_Record(), core_lib);
    pending_classes.Add(cls);

    cls = Class::New<WeakProperty, RTN::WeakProperty>(isolate_group);
    object_store->set_weak_property_class(cls);
    RegisterPrivateClass(cls, Symbols::_WeakProperty(), core_lib);

    cls = Class::New<WeakReference, RTN::WeakReference>(isolate_group);
    cls.set_type_arguments_field_offset(
        WeakReference::type_arguments_offset(),
        RTN::WeakReference::type_arguments_offset());
    cls.set_num_type_arguments_unsafe(1);
    object_store->set_weak_reference_class(cls);
    RegisterPrivateClass(cls, Symbols::_WeakReference(), core_lib);

    // Pre-register the mirrors library so we can place the vm class
    // MirrorReference there rather than the core library.
    lib = Library::LookupLibrary(thread, Symbols::DartMirrors());
    if (lib.IsNull()) {
      lib = Library::NewLibraryHelper(Symbols::DartMirrors(), true);
      lib.SetLoadRequested();
      lib.Register(thread);
    }
    object_store->set_bootstrap_library(ObjectStore::kMirrors, lib);
    ASSERT(!lib.IsNull());
    ASSERT(lib.ptr() == Library::MirrorsLibrary());

    cls = Class::New<MirrorReference, RTN::MirrorReference>(isolate_group);
    RegisterPrivateClass(cls, Symbols::_MirrorReference(), lib);

    // Pre-register dart:_compact_hash library so that we could place
    // collection classes (_Map, _ConstMap, _Set, _ConstSet) here.
    lib = Library::LookupLibrary(thread, Symbols::DartCompactHash());
    if (lib.IsNull()) {
      lib = Library::NewLibraryHelper(Symbols::DartCompactHash(), true);
      lib.SetLoadRequested();
      lib.Register(thread);
    }
    object_store->set_bootstrap_library(ObjectStore::kCompactHash, lib);

    ASSERT(!lib.IsNull());
    ASSERT(lib.ptr() == Library::CompactHashLibrary());
    cls = Class::New<Map, RTN::Map>(isolate_group);
    object_store->set_map_impl_class(cls);
    cls.set_type_arguments_field_offset(Map::type_arguments_offset(),
                                        RTN::Map::type_arguments_offset());
    cls.set_num_type_arguments_unsafe(2);
    RegisterPrivateClass(cls, Symbols::_Map(), lib);
    pending_classes.Add(cls);

    cls = Class::New<Map, RTN::Map>(kConstMapCid, isolate_group);
    object_store->set_const_map_impl_class(cls);
    cls.set_type_arguments_field_offset(Map::type_arguments_offset(),
                                        RTN::Map::type_arguments_offset());
    cls.set_num_type_arguments_unsafe(2);
    cls.set_is_prefinalized();
    RegisterPrivateClass(cls, Symbols::_ConstMap(), lib);
    pending_classes.Add(cls);

    cls = Class::New<Set, RTN::Set>(isolate_group);
    object_store->set_set_impl_class(cls);
    cls.set_type_arguments_field_offset(Set::type_arguments_offset(),
                                        RTN::Set::type_arguments_offset());
    cls.set_num_type_arguments_unsafe(1);
    RegisterPrivateClass(cls, Symbols::_Set(), lib);
    pending_classes.Add(cls);

    cls = Class::New<Set, RTN::Set>(kConstSetCid, isolate_group);
    object_store->set_const_set_impl_class(cls);
    cls.set_type_arguments_field_offset(Set::type_arguments_offset(),
                                        RTN::Set::type_arguments_offset());
    cls.set_num_type_arguments_unsafe(1);
    cls.set_is_prefinalized();
    RegisterPrivateClass(cls, Symbols::_ConstSet(), lib);
    pending_classes.Add(cls);

    // Pre-register the collection library.
    lib = Library::LookupLibrary(thread, Symbols::DartCollection());
    if (lib.IsNull()) {
      lib = Library::NewLibraryHelper(Symbols::DartCollection(), true);
      lib.SetLoadRequested();
      lib.Register(thread);
    }
    object_store->set_bootstrap_library(ObjectStore::kCollection, lib);

    // Pre-register the async library so we can place the vm class
    // FutureOr there rather than the core library.
    lib = Library::LookupLibrary(thread, Symbols::DartAsync());
    if (lib.IsNull()) {
      lib = Library::NewLibraryHelper(Symbols::DartAsync(), true);
      lib.SetLoadRequested();
      lib.Register(thread);
    }
    object_store->set_bootstrap_library(ObjectStore::kAsync, lib);
    ASSERT(!lib.IsNull());
    ASSERT(lib.ptr() == Library::AsyncLibrary());
    cls = Class::New<FutureOr, RTN::FutureOr>(isolate_group);
    cls.set_type_arguments_field_offset(FutureOr::type_arguments_offset(),
                                        RTN::FutureOr::type_arguments_offset());
    cls.set_num_type_arguments_unsafe(1);
    RegisterClass(cls, Symbols::FutureOr(), lib);
    pending_classes.Add(cls);
    object_store->set_future_or_class(cls);

    cls = Class::New<SuspendState, RTN::SuspendState>(isolate_group);
    RegisterPrivateClass(cls, Symbols::_SuspendState(), lib);
    pending_classes.Add(cls);

    // Pre-register the developer library so we can place the vm class
    // UserTag there rather than the core library.
    lib = Library::LookupLibrary(thread, Symbols::DartDeveloper());
    if (lib.IsNull()) {
      lib = Library::NewLibraryHelper(Symbols::DartDeveloper(), true);
      lib.SetLoadRequested();
      lib.Register(thread);
    }
    object_store->set_bootstrap_library(ObjectStore::kDeveloper, lib);
    ASSERT(!lib.IsNull());
    ASSERT(lib.ptr() == Library::DeveloperLibrary());
    cls = Class::New<UserTag, RTN::UserTag>(isolate_group);
    RegisterPrivateClass(cls, Symbols::_UserTag(), lib);
    pending_classes.Add(cls);

    // Setup some default native field classes which can be extended for
    // specifying native fields in dart classes.
    Library::InitNativeWrappersLibrary(isolate_group, is_kernel);
    ASSERT(object_store->native_wrappers_library() != Library::null());

    // Pre-register the typed_data library so the native class implementations
    // can be hooked up before compiling it.
    lib = Library::LookupLibrary(thread, Symbols::DartTypedData());
    if (lib.IsNull()) {
      lib = Library::NewLibraryHelper(Symbols::DartTypedData(), true);
      lib.SetLoadRequested();
      lib.Register(thread);
    }
    object_store->set_bootstrap_library(ObjectStore::kTypedData, lib);
    ASSERT(!lib.IsNull());
    ASSERT(lib.ptr() == Library::TypedDataLibrary());
#define REGISTER_TYPED_DATA_CLASS(clazz)                                       \
  cls = Class::NewTypedDataClass(kTypedData##clazz##ArrayCid, isolate_group);  \
  RegisterPrivateClass(cls, Symbols::_##clazz##List(), lib);

    DART_CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_CLASS);
#undef REGISTER_TYPED_DATA_CLASS
#define REGISTER_TYPED_DATA_VIEW_CLASS(clazz)                                  \
  cls =                                                                        \
      Class::NewTypedDataViewClass(kTypedData##clazz##ViewCid, isolate_group); \
  RegisterPrivateClass(cls, Symbols::_##clazz##View(), lib);                   \
  pending_classes.Add(cls);                                                    \
  cls = Class::NewUnmodifiableTypedDataViewClass(                              \
      kUnmodifiableTypedData##clazz##ViewCid, isolate_group);                  \
  RegisterPrivateClass(cls, Symbols::_Unmodifiable##clazz##View(), lib);       \
  pending_classes.Add(cls);

    CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_VIEW_CLASS);

    cls = Class::NewTypedDataViewClass(kByteDataViewCid, isolate_group);
    RegisterPrivateClass(cls, Symbols::_ByteDataView(), lib);
    pending_classes.Add(cls);
    cls = Class::NewUnmodifiableTypedDataViewClass(kUnmodifiableByteDataViewCid,
                                                   isolate_group);
    RegisterPrivateClass(cls, Symbols::_UnmodifiableByteDataView(), lib);
    pending_classes.Add(cls);

#undef REGISTER_TYPED_DATA_VIEW_CLASS
#define REGISTER_EXT_TYPED_DATA_CLASS(clazz)                                   \
  cls = Class::NewExternalTypedDataClass(kExternalTypedData##clazz##Cid,       \
                                         isolate_group);                       \
  RegisterPrivateClass(cls, Symbols::_External##clazz(), lib);

    cls = Class::New<Instance, RTN::Instance>(kByteBufferCid, isolate_group,
                                              /*register_class=*/false);
    cls.set_instance_size(0, 0);
    cls.set_next_field_offset(-kWordSize, -compiler::target::kWordSize);
    isolate_group->class_table()->Register(cls);
    RegisterPrivateClass(cls, Symbols::_ByteBuffer(), lib);
    pending_classes.Add(cls);

    CLASS_LIST_TYPED_DATA(REGISTER_EXT_TYPED_DATA_CLASS);
#undef REGISTER_EXT_TYPED_DATA_CLASS
    // Register Float32x4, Int32x4, and Float64x2 in the object store.
    cls = Class::New<Float32x4, RTN::Float32x4>(isolate_group);
    RegisterPrivateClass(cls, Symbols::_Float32x4(), lib);
    pending_classes.Add(cls);
    object_store->set_float32x4_class(cls);

    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                              /*register_class=*/true,
                                              /*is_abstract=*/true);
    RegisterClass(cls, Symbols::Float32x4(), lib);
    cls.set_num_type_arguments_unsafe(0);
    cls.set_is_prefinalized();
    type = Type::NewNonParameterizedType(cls);
    object_store->set_float32x4_type(type);

    cls = Class::New<Int32x4, RTN::Int32x4>(isolate_group);
    RegisterPrivateClass(cls, Symbols::_Int32x4(), lib);
    pending_classes.Add(cls);
    object_store->set_int32x4_class(cls);

    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                              /*register_class=*/true,
                                              /*is_abstract=*/true);
    RegisterClass(cls, Symbols::Int32x4(), lib);
    cls.set_num_type_arguments_unsafe(0);
    cls.set_is_prefinalized();
    type = Type::NewNonParameterizedType(cls);
    object_store->set_int32x4_type(type);

    cls = Class::New<Float64x2, RTN::Float64x2>(isolate_group);
    RegisterPrivateClass(cls, Symbols::_Float64x2(), lib);
    pending_classes.Add(cls);
    object_store->set_float64x2_class(cls);

    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                              /*register_class=*/true,
                                              /*is_abstract=*/true);
    RegisterClass(cls, Symbols::Float64x2(), lib);
    cls.set_num_type_arguments_unsafe(0);
    cls.set_is_prefinalized();
    type = Type::NewNonParameterizedType(cls);
    object_store->set_float64x2_type(type);

    // Set the super type of class StackTrace to Object type so that the
    // 'toString' method is implemented.
    type = object_store->object_type();
    stacktrace_cls.set_super_type(type);

    // Abstract class that represents the Dart class Type.
    // Note that this class is implemented by Dart class _AbstractType.
    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                              /*register_class=*/true,
                                              /*is_abstract=*/true);
    cls.set_num_type_arguments_unsafe(0);
    cls.set_is_prefinalized();
    RegisterClass(cls, Symbols::Type(), core_lib);
    pending_classes.Add(cls);
    type = Type::NewNonParameterizedType(cls);
    object_store->set_type_type(type);

    // Abstract class that represents the Dart class Function.
    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                              /*register_class=*/true,
                                              /*is_abstract=*/true);
    cls.set_num_type_arguments_unsafe(0);
    cls.set_is_prefinalized();
    RegisterClass(cls, Symbols::Function(), core_lib);
    pending_classes.Add(cls);
    type = Type::NewNonParameterizedType(cls);
    object_store->set_function_type(type);

    // Abstract class that represents the Dart class Record.
    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                              /*register_class=*/true,
                                              /*is_abstract=*/true);
    RegisterClass(cls, Symbols::Record(), core_lib);
    pending_classes.Add(cls);
    object_store->set_record_class(cls);

    cls = Class::New<Number, RTN::Number>(isolate_group);
    RegisterClass(cls, Symbols::Number(), core_lib);
    pending_classes.Add(cls);
    type = Type::NewNonParameterizedType(cls);
    object_store->set_number_type(type);
    type = type.ToNullability(Nullability::kNullable, Heap::kOld);
    object_store->set_nullable_number_type(type);

    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                              /*register_class=*/true,
                                              /*is_abstract=*/true);
    RegisterClass(cls, Symbols::Int(), core_lib);
    cls.set_num_type_arguments_unsafe(0);
    cls.set_is_prefinalized();
    pending_classes.Add(cls);
    type = Type::NewNonParameterizedType(cls);
    object_store->set_int_type(type);
    type = type.ToNullability(Nullability::kNonNullable, Heap::kOld);
    object_store->set_non_nullable_int_type(type);
    type = type.ToNullability(Nullability::kNullable, Heap::kOld);
    object_store->set_nullable_int_type(type);

    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                              /*register_class=*/true,
                                              /*is_abstract=*/true);
    RegisterClass(cls, Symbols::Double(), core_lib);
    cls.set_num_type_arguments_unsafe(0);
    cls.set_is_prefinalized();
    pending_classes.Add(cls);
    type = Type::NewNonParameterizedType(cls);
    object_store->set_double_type(type);
    type = type.ToNullability(Nullability::kNullable, Heap::kOld);
    object_store->set_nullable_double_type(type);

    name = Symbols::_String().ptr();
    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                              /*register_class=*/true,
                                              /*is_abstract=*/true);
    RegisterClass(cls, name, core_lib);
    cls.set_num_type_arguments_unsafe(0);
    cls.set_is_prefinalized();
    pending_classes.Add(cls);
    type = Type::NewNonParameterizedType(cls);
    object_store->set_string_type(type);

    cls = object_store->bool_class();
    type = Type::NewNonParameterizedType(cls);
    object_store->set_bool_type(type);

    cls = object_store->smi_class();
    type = Type::NewNonParameterizedType(cls);
    object_store->set_smi_type(type);

    cls = object_store->mint_class();
    type = Type::NewNonParameterizedType(cls);
    object_store->set_mint_type(type);

    // The classes 'void' and 'dynamic' are phony classes to make type checking
    // more regular; they live in the VM isolate. The class 'void' is not
    // registered in the class dictionary because its name is a reserved word.
    // The class 'dynamic' is registered in the class dictionary because its
    // name is a built-in identifier (this is wrong).  The corresponding types
    // are stored in the object store.
    cls = object_store->null_class();
    type =
        Type::New(cls, Object::null_type_arguments(), Nullability::kNullable);
    type.SetIsFinalized();
    type ^= type.Canonicalize(thread);
    object_store->set_null_type(type);
    cls.set_declaration_type(type);
    ASSERT(type.IsNullable());

    // Consider removing when/if Null becomes an ordinary class.
    type = object_store->object_type();
    cls.set_super_type(type);

    cls = object_store->never_class();
    type = Type::New(cls, Object::null_type_arguments(),
                     Nullability::kNonNullable);
    type.SetIsFinalized();
    type ^= type.Canonicalize(thread);
    object_store->set_never_type(type);
    type_args = TypeArguments::New(1);
    type_args.SetTypeAt(0, type);
    type_args = type_args.Canonicalize(thread);
    object_store->set_type_argument_never(type_args);

    // Create and cache commonly used type arguments <int>, <double>,
    // <String>, <String, dynamic> and <String, String>.
    type_args = TypeArguments::New(1);
    type = object_store->int_type();
    type_args.SetTypeAt(0, type);
    type_args = type_args.Canonicalize(thread);
    object_store->set_type_argument_int(type_args);

    type_args = TypeArguments::New(1);
    type = object_store->double_type();
    type_args.SetTypeAt(0, type);
    type_args = type_args.Canonicalize(thread);
    object_store->set_type_argument_double(type_args);

    type_args = TypeArguments::New(1);
    type = object_store->string_type();
    type_args.SetTypeAt(0, type);
    type_args = type_args.Canonicalize(thread);
    object_store->set_type_argument_string(type_args);

    type_args = TypeArguments::New(2);
    type = object_store->string_type();
    type_args.SetTypeAt(0, type);
    type_args.SetTypeAt(1, Object::dynamic_type());
    type_args = type_args.Canonicalize(thread);
    object_store->set_type_argument_string_dynamic(type_args);

    type_args = TypeArguments::New(2);
    type = object_store->string_type();
    type_args.SetTypeAt(0, type);
    type_args.SetTypeAt(1, type);
    type_args = type_args.Canonicalize(thread);
    object_store->set_type_argument_string_string(type_args);

    lib = Library::LookupLibrary(thread, Symbols::DartFfi());
    if (lib.IsNull()) {
      lib = Library::NewLibraryHelper(Symbols::DartFfi(), true);
      lib.SetLoadRequested();
      lib.Register(thread);
    }
    object_store->set_bootstrap_library(ObjectStore::kFfi, lib);

    cls = Class::New<Instance, RTN::Instance>(kFfiNativeTypeCid, isolate_group);
    cls.set_num_type_arguments_unsafe(0);
    cls.set_is_prefinalized();
    pending_classes.Add(cls);
    object_store->set_ffi_native_type_class(cls);
    RegisterClass(cls, Symbols::FfiNativeType(), lib);

#define REGISTER_FFI_TYPE_MARKER(clazz)                                        \
  cls = Class::New<Instance, RTN::Instance>(kFfi##clazz##Cid, isolate_group);  \
  cls.set_num_type_arguments_unsafe(0);                                        \
  cls.set_is_prefinalized();                                                   \
  pending_classes.Add(cls);                                                    \
  RegisterClass(cls, Symbols::Ffi##clazz(), lib);
    CLASS_LIST_FFI_TYPE_MARKER(REGISTER_FFI_TYPE_MARKER);
#undef REGISTER_FFI_TYPE_MARKER

    cls = Class::New<Instance, RTN::Instance>(kFfiNativeFunctionCid,
                                              isolate_group);
    cls.set_type_arguments_field_offset(Instance::NextFieldOffset(),
                                        RTN::Instance::NextFieldOffset());
    cls.set_num_type_arguments_unsafe(1);
    cls.set_is_prefinalized();
    pending_classes.Add(cls);
    RegisterClass(cls, Symbols::FfiNativeFunction(), lib);

    cls = Class::NewPointerClass(kPointerCid, isolate_group);
    object_store->set_ffi_pointer_class(cls);
    pending_classes.Add(cls);
    RegisterClass(cls, Symbols::FfiPointer(), lib);

    cls = Class::New<DynamicLibrary, RTN::DynamicLibrary>(kDynamicLibraryCid,
                                                          isolate_group);
    cls.set_instance_size(DynamicLibrary::InstanceSize(),
                          compiler::target::RoundedAllocationSize(
                              RTN::DynamicLibrary::InstanceSize()));
    cls.set_is_prefinalized();
    pending_classes.Add(cls);
    RegisterClass(cls, Symbols::FfiDynamicLibrary(), lib);

    cls = Class::New<NativeFinalizer, RTN::NativeFinalizer>(isolate_group);
    object_store->set_native_finalizer_class(cls);
    RegisterPrivateClass(cls, Symbols::_NativeFinalizer(), lib);

    cls = Class::New<Finalizer, RTN::Finalizer>(isolate_group);
    cls.set_type_arguments_field_offset(
        Finalizer::type_arguments_offset(),
        RTN::Finalizer::type_arguments_offset());
    cls.set_num_type_arguments_unsafe(1);
    object_store->set_finalizer_class(cls);
    pending_classes.Add(cls);
    RegisterPrivateClass(cls, Symbols::_FinalizerImpl(), core_lib);

    // Pre-register the internal library so we can place the vm class
    // FinalizerEntry there rather than the core library.
    lib = Library::LookupLibrary(thread, Symbols::DartInternal());
    if (lib.IsNull()) {
      lib = Library::NewLibraryHelper(Symbols::DartInternal(), true);
      lib.SetLoadRequested();
      lib.Register(thread);
    }
    object_store->set_bootstrap_library(ObjectStore::kInternal, lib);
    ASSERT(!lib.IsNull());
    ASSERT(lib.ptr() == Library::InternalLibrary());

    cls = Class::New<FinalizerEntry, RTN::FinalizerEntry>(isolate_group);
    object_store->set_finalizer_entry_class(cls);
    pending_classes.Add(cls);
    RegisterClass(cls, Symbols::FinalizerEntry(), lib);

    // Finish the initialization by compiling the bootstrap scripts containing
    // the base interfaces and the implementation of the internal classes.
    const Error& error = Error::Handle(
        zone, Bootstrap::DoBootstrapping(kernel_buffer, kernel_buffer_size));
    if (!error.IsNull()) {
      return error.ptr();
    }

    isolate_group->class_table()->CopySizesFromClassObjects();

    ClassFinalizer::VerifyBootstrapClasses();

    // Adds static const fields (class ids) to the class 'ClassID');
    lib = Library::LookupLibrary(thread, Symbols::DartInternal());
    ASSERT(!lib.IsNull());
    cls = lib.LookupClassAllowPrivate(Symbols::ClassID());
    ASSERT(!cls.IsNull());
    const bool injected = cls.InjectCIDFields();
    ASSERT(injected);

    // Set up recognized state of all functions (core, math and typed data).
    MethodRecognizer::InitializeState();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  } else {
    // Object::Init version when we are running in a version of dart that has a
    // full snapshot linked in and an isolate is initialized using the full
    // snapshot.
    ObjectStore* object_store = isolate_group->object_store();
    SafepointWriteRwLocker ml(thread, isolate_group->program_lock());

    Class& cls = Class::Handle(zone);

    // Set up empty classes in the object store, these will get initialized
    // correctly when we read from the snapshot.  This is done to allow
    // bootstrapping of reading classes from the snapshot.  Some classes are not
    // stored in the object store. Yet we still need to create their Class
    // object so that they get put into the class_table (as a side effect of
    // Class::New()).
    cls = Class::New<Instance, RTN::Instance>(kInstanceCid, isolate_group);
    object_store->set_object_class(cls);

    cls = Class::New<LibraryPrefix, RTN::LibraryPrefix>(isolate_group);
    cls = Class::New<Type, RTN::Type>(isolate_group);
    cls = Class::New<FunctionType, RTN::FunctionType>(isolate_group);
    cls = Class::New<RecordType, RTN::RecordType>(isolate_group);
    cls = Class::New<TypeParameter, RTN::TypeParameter>(isolate_group);

    cls = Class::New<Array, RTN::Array>(isolate_group);
    object_store->set_array_class(cls);

    cls = Class::New<Array, RTN::Array>(kImmutableArrayCid, isolate_group);
    object_store->set_immutable_array_class(cls);

    cls = Class::New<GrowableObjectArray, RTN::GrowableObjectArray>(
        isolate_group);
    object_store->set_growable_object_array_class(cls);

    cls = Class::New<Map, RTN::Map>(isolate_group);
    object_store->set_map_impl_class(cls);

    cls = Class::New<Map, RTN::Map>(kConstMapCid, isolate_group);
    object_store->set_const_map_impl_class(cls);

    cls = Class::New<Set, RTN::Set>(isolate_group);
    object_store->set_set_impl_class(cls);

    cls = Class::New<Set, RTN::Set>(kConstSetCid, isolate_group);
    object_store->set_const_set_impl_class(cls);

    cls = Class::New<Float32x4, RTN::Float32x4>(isolate_group);
    object_store->set_float32x4_class(cls);

    cls = Class::New<Int32x4, RTN::Int32x4>(isolate_group);
    object_store->set_int32x4_class(cls);

    cls = Class::New<Float64x2, RTN::Float64x2>(isolate_group);
    object_store->set_float64x2_class(cls);

#define REGISTER_TYPED_DATA_CLASS(clazz)                                       \
  cls = Class::NewTypedDataClass(kTypedData##clazz##Cid, isolate_group);
    CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_CLASS);
#undef REGISTER_TYPED_DATA_CLASS
#define REGISTER_TYPED_DATA_VIEW_CLASS(clazz)                                  \
  cls =                                                                        \
      Class::NewTypedDataViewClass(kTypedData##clazz##ViewCid, isolate_group); \
  cls = Class::NewUnmodifiableTypedDataViewClass(                              \
      kUnmodifiableTypedData##clazz##ViewCid, isolate_group);
    CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_VIEW_CLASS);
#undef REGISTER_TYPED_DATA_VIEW_CLASS
    cls = Class::NewTypedDataViewClass(kByteDataViewCid, isolate_group);
    cls = Class::NewUnmodifiableTypedDataViewClass(kUnmodifiableByteDataViewCid,
                                                   isolate_group);
#define REGISTER_EXT_TYPED_DATA_CLASS(clazz)                                   \
  cls = Class::NewExternalTypedDataClass(kExternalTypedData##clazz##Cid,       \
                                         isolate_group);
    CLASS_LIST_TYPED_DATA(REGISTER_EXT_TYPED_DATA_CLASS);
#undef REGISTER_EXT_TYPED_DATA_CLASS

    cls = Class::New<Instance, RTN::Instance>(kFfiNativeTypeCid, isolate_group);
    object_store->set_ffi_native_type_class(cls);

#define REGISTER_FFI_CLASS(clazz)                                              \
  cls = Class::New<Instance, RTN::Instance>(kFfi##clazz##Cid, isolate_group);
    CLASS_LIST_FFI_TYPE_MARKER(REGISTER_FFI_CLASS);
#undef REGISTER_FFI_CLASS

    cls = Class::New<Instance, RTN::Instance>(kFfiNativeFunctionCid,
                                              isolate_group);

    cls = Class::NewPointerClass(kPointerCid, isolate_group);
    object_store->set_ffi_pointer_class(cls);

    cls = Class::New<DynamicLibrary, RTN::DynamicLibrary>(kDynamicLibraryCid,
                                                          isolate_group);

    cls = Class::New<Instance, RTN::Instance>(kByteBufferCid, isolate_group,
                                              /*register_class=*/false);
    cls.set_instance_size_in_words(0, 0);
    isolate_group->class_table()->Register(cls);

    cls = Class::New<Integer, RTN::Integer>(isolate_group);
    object_store->set_integer_implementation_class(cls);

    cls = Class::New<Smi, RTN::Smi>(isolate_group);
    object_store->set_smi_class(cls);

    cls = Class::New<Mint, RTN::Mint>(isolate_group);
    object_store->set_mint_class(cls);

    cls = Class::New<Double, RTN::Double>(isolate_group);
    object_store->set_double_class(cls);

    cls = Class::New<Closure, RTN::Closure>(isolate_group);
    object_store->set_closure_class(cls);

    cls = Class::New<Record, RTN::Record>(isolate_group);

    cls = Class::NewStringClass(kOneByteStringCid, isolate_group);
    object_store->set_one_byte_string_class(cls);

    cls = Class::NewStringClass(kTwoByteStringCid, isolate_group);
    object_store->set_two_byte_string_class(cls);

    cls = Class::New<Bool, RTN::Bool>(isolate_group);
    object_store->set_bool_class(cls);

    cls = Class::New<Instance, RTN::Instance>(kNullCid, isolate_group);
    object_store->set_null_class(cls);

    cls = Class::New<Instance, RTN::Instance>(kNeverCid, isolate_group);
    object_store->set_never_class(cls);

    cls = Class::New<Capability, RTN::Capability>(isolate_group);
    cls = Class::New<ReceivePort, RTN::ReceivePort>(isolate_group);
    cls = Class::New<SendPort, RTN::SendPort>(isolate_group);
    cls = Class::New<StackTrace, RTN::StackTrace>(isolate_group);
    cls = Class::New<SuspendState, RTN::SuspendState>(isolate_group);
    cls = Class::New<RegExp, RTN::RegExp>(isolate_group);
    cls = Class::New<Number, RTN::Number>(isolate_group);

    cls = Class::New<WeakProperty, RTN::WeakProperty>(isolate_group);
    object_store->set_weak_property_class(cls);
    cls = Class::New<WeakReference, RTN::WeakReference>(isolate_group);
    object_store->set_weak_reference_class(cls);
    cls = Class::New<Finalizer, RTN::Finalizer>(isolate_group);
    object_store->set_finalizer_class(cls);
    cls = Class::New<NativeFinalizer, RTN::NativeFinalizer>(isolate_group);
    object_store->set_native_finalizer_class(cls);
    cls = Class::New<FinalizerEntry, RTN::FinalizerEntry>(isolate_group);
    object_store->set_finalizer_entry_class(cls);

    cls = Class::New<MirrorReference, RTN::MirrorReference>(isolate_group);
    cls = Class::New<UserTag, RTN::UserTag>(isolate_group);
    cls = Class::New<FutureOr, RTN::FutureOr>(isolate_group);
    object_store->set_future_or_class(cls);
    cls = Class::New<TransferableTypedData, RTN::TransferableTypedData>(
        isolate_group);
  }
  return Error::null();
}

#if defined(DEBUG)
bool Object::InVMIsolateHeap() const {
  return ptr()->untag()->InVMIsolateHeap();
}
#endif  // DEBUG

void Object::Print() const {
  THR_Print("%s\n", ToCString());
}

StringPtr Object::DictionaryName() const {
  return String::null();
}

bool Object::ShouldHaveImmutabilityBitSet(classid_t class_id) {
  if (class_id < kNumPredefinedCids) {
    return ShouldHaveImmutabilityBitSetCid(class_id);
  } else {
    return Class::IsDeeplyImmutable(
        IsolateGroup::Current()->class_table()->At(class_id));
  }
}

void Object::InitializeObject(uword address,
                              intptr_t class_id,
                              intptr_t size,
                              bool compressed,
                              uword ptr_field_start_offset,
                              uword ptr_field_end_offset) {
  // Note: we skip the header word here to avoid a racy read in the concurrent
  // marker from observing the null object when it reads into a heap page
  // allocated after marking started.
  uword cur = address + sizeof(UntaggedObject);
  uword ptr_field_start = address + ptr_field_start_offset;
  uword ptr_field_end = address + ptr_field_end_offset;
  uword end = address + size;
  // The start of pointer fields should always be past the object header, even
  // if there are no pointer fields (ptr_field_end < ptr_field_start).
  ASSERT(cur <= ptr_field_start);
  // The start of pointer fields can be at the end for empty payload objects.
  ASSERT(ptr_field_start <= end);
  // The end of pointer fields should always be before the end, as the end of
  // pointer fields is inclusive (the address of the last field to initialize).
  ASSERT(ptr_field_end < end);
  bool needs_init = true;
  if (IsTypedDataBaseClassId(class_id) || class_id == kArrayCid) {
    // If the size is greater than both kNewAllocatableSize and
    // kAllocatablePageSize, the object must have been allocated to a new
    // large page, which must already have been zero initialized by the OS.
    // Note that zero is a GC-safe value.
    //
    // For arrays, the caller will then initialize the fields to null with
    // safepoint checks to avoid blocking for the full duration of
    // initializing this array.
    needs_init =
        IsAllocatableInNewSpace(size) || IsAllocatableViaFreeLists(size);
  }
  if (needs_init) {
    // Initialize the memory prior to any pointer fields with 0. (This loop
    // and the next will be a no-op if the object has no pointer fields.)
    uword initial_value = 0;
    while (cur < ptr_field_start) {
      *reinterpret_cast<uword*>(cur) = initial_value;
      cur += kWordSize;
    }
    // Initialize any pointer fields with Object::null().
    initial_value = static_cast<uword>(null_);
#if defined(DART_COMPRESSED_POINTERS)
    if (compressed) {
      initial_value &= 0xFFFFFFFF;
      initial_value |= initial_value << 32;
    }
    const bool has_pointer_fields = ptr_field_start <= ptr_field_end;
    // If there are compressed pointer fields and the first compressed pointer
    // field is not at a word start, then initialize it to Object::null().
    if (compressed && has_pointer_fields &&
        (ptr_field_start % kWordSize != 0)) {
      *reinterpret_cast<compressed_uword*>(ptr_field_start) = initial_value;
    }
#endif
    while (cur <= ptr_field_end) {
      *reinterpret_cast<uword*>(cur) = initial_value;
      cur += kWordSize;
    }
    // Initialize the memory after any pointer fields with 0, unless this is
    // an instructions object in which case we use the break instruction.
    initial_value = class_id == kInstructionsCid ? kBreakInstructionFiller : 0;
#if defined(DART_COMPRESSED_POINTERS)
    // If there are compressed pointer fields and the last compressed pointer
    // field is the start of a word, then initialize the other part of the word
    // to the new initial value.
    //
    // (We're guaranteed there's always space in the object after the last
    // pointer field in this case since objects are allocated in multiples of
    // the word size.)
    if (compressed && has_pointer_fields && (ptr_field_end % kWordSize == 0)) {
      *reinterpret_cast<compressed_uword*>(ptr_field_end +
                                           kCompressedWordSize) = initial_value;
    }
#endif
    while (cur < end) {
      *reinterpret_cast<uword*>(cur) = initial_value;
      cur += kWordSize;
    }
  } else {
    // Check that MemorySanitizer understands this is initialized.
    MSAN_CHECK_INITIALIZED(reinterpret_cast<void*>(address), size);
#if defined(DEBUG)
    const uword initial_value = 0;
    while (cur < end) {
      ASSERT_EQUAL(*reinterpret_cast<uword*>(cur), initial_value);
      cur += kWordSize;
    }
#endif
  }
  uword tags = 0;
  ASSERT(class_id != kIllegalCid);
  tags = UntaggedObject::ClassIdTag::update(class_id, tags);
  tags = UntaggedObject::SizeTag::update(size, tags);
  const bool is_old =
      (address & kNewObjectAlignmentOffset) == kOldObjectAlignmentOffset;
  tags = UntaggedObject::AlwaysSetBit::update(true, tags);
  tags = UntaggedObject::NotMarkedBit::update(true, tags);
  tags = UntaggedObject::OldAndNotRememberedBit::update(is_old, tags);
  tags = UntaggedObject::NewOrEvacuationCandidateBit::update(!is_old, tags);
  tags = UntaggedObject::ImmutableBit::update(
      Object::ShouldHaveImmutabilityBitSet(class_id), tags);
#if defined(HASH_IN_OBJECT_HEADER)
  tags = UntaggedObject::HashTag::update(0, tags);
#endif

  reinterpret_cast<UntaggedObject*>(address)->tags_ = tags;
#if defined(HOST_HAS_FAST_WRITE_WRITE_FENCE)
  std::atomic_thread_fence(std::memory_order_release);
#endif
}

void Object::CheckHandle() const {
#if defined(DEBUG)
  if (ptr_ != Object::null()) {
    intptr_t cid = ptr_->GetClassId();
    if (cid >= kNumPredefinedCids) {
      cid = kInstanceCid;
    }
    ASSERT(vtable() == builtin_vtables_[cid]);
  }
#endif
}

ObjectPtr Object::Allocate(intptr_t cls_id,
                           intptr_t size,
                           Heap::Space space,
                           bool compressed,
                           uword ptr_field_start_offset,
                           uword ptr_field_end_offset) {
  ASSERT(Utils::IsAligned(size, kObjectAlignment));
  Thread* thread = Thread::Current();
  ASSERT(thread->execution_state() == Thread::kThreadInVM);
  ASSERT(thread->no_safepoint_scope_depth() == 0);
  ASSERT(thread->no_callback_scope_depth() == 0);
  Heap* heap = thread->heap();

  uword address = heap->Allocate(thread, size, space);
  if (UNLIKELY(address == 0)) {
    // SuspendLongJumpScope during Dart entry ensures that if a longjmp base is
    // available, it is the innermost error handler, so check for a longjmp base
    // before checking for an exit frame.
    if (thread->long_jump_base() != nullptr) {
      Report::LongJump(Object::out_of_memory_error());
      UNREACHABLE();
    } else if (thread->top_exit_frame_info() != 0) {
      Exceptions::ThrowOOM();
      UNREACHABLE();
    } else {
      // Nowhere to propagate an exception to.
      OUT_OF_MEMORY();
    }
  }

  ObjectPtr raw_obj;
  NoSafepointScope no_safepoint(thread);
  InitializeObject(address, cls_id, size, compressed, ptr_field_start_offset,
                   ptr_field_end_offset);
  raw_obj = static_cast<ObjectPtr>(address + kHeapObjectTag);
  ASSERT(cls_id == UntaggedObject::ClassIdTag::decode(raw_obj->untag()->tags_));
  if (raw_obj->IsOldObject() && UNLIKELY(thread->is_marking())) {
    // Black allocation. Prevents a data race between the mutator and
    // concurrent marker on ARM and ARM64 (the marker may observe a
    // publishing store of this object before the stores that initialize its
    // slots), and helps the collection to finish sooner.
    // release: Setting the mark bit must not be ordered after a publishing
    // store of this object. Compare Scavenger::ScavengePointer.
    raw_obj->untag()->SetMarkBitRelease();
    heap->old_space()->AllocateBlack(size);
  }

#if !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
  HeapProfileSampler& heap_sampler = thread->heap_sampler();
  if (heap_sampler.HasOutstandingSample()) {
    thread->IncrementNoCallbackScopeDepth();
    void* data = heap_sampler.InvokeCallbackForLastSample(cls_id);
    heap->SetHeapSamplingData(raw_obj, data);
    thread->DecrementNoCallbackScopeDepth();
  }
#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)

#if !defined(PRODUCT)
  auto class_table = thread->isolate_group()->class_table();
  if (class_table->ShouldTraceAllocationFor(cls_id)) {
    uint32_t hash =
        HeapSnapshotWriter::GetHeapSnapshotIdentityHash(thread, raw_obj);
    Profiler::SampleAllocation(thread, cls_id, hash);
  }
#endif  // !defined(PRODUCT)
  return raw_obj;
}

class WriteBarrierUpdateVisitor : public ObjectPointerVisitor {
 public:
  explicit WriteBarrierUpdateVisitor(Thread* thread, ObjectPtr obj)
      : ObjectPointerVisitor(thread->isolate_group()),
        thread_(thread),
        old_obj_(obj) {
    ASSERT(old_obj_->IsOldObject());
  }

  void VisitPointers(ObjectPtr* from, ObjectPtr* to) override {
    if (old_obj_->IsArray()) {
      for (ObjectPtr* slot = from; slot <= to; ++slot) {
        ObjectPtr value = *slot;
        if (value->IsHeapObject()) {
          old_obj_->untag()->CheckArrayPointerStore(slot, value, thread_);
        }
      }
    } else {
      for (ObjectPtr* slot = from; slot <= to; ++slot) {
        ObjectPtr value = *slot;
        if (value->IsHeapObject()) {
          old_obj_->untag()->CheckHeapPointerStore(value, thread_);
        }
      }
    }
  }

#if defined(DART_COMPRESSED_POINTERS)
  void VisitCompressedPointers(uword heap_base,
                               CompressedObjectPtr* from,
                               CompressedObjectPtr* to) override {
    if (old_obj_->IsArray()) {
      for (CompressedObjectPtr* slot = from; slot <= to; ++slot) {
        ObjectPtr value = slot->Decompress(heap_base);
        if (value->IsHeapObject()) {
          old_obj_->untag()->CheckArrayPointerStore(slot, value, thread_);
        }
      }
    } else {
      for (CompressedObjectPtr* slot = from; slot <= to; ++slot) {
        ObjectPtr value = slot->Decompress(heap_base);
        if (value->IsHeapObject()) {
          old_obj_->untag()->CheckHeapPointerStore(value, thread_);
        }
      }
    }
  }
#endif

 private:
  Thread* thread_;
  ObjectPtr old_obj_;

  DISALLOW_COPY_AND_ASSIGN(WriteBarrierUpdateVisitor);
};

#if defined(DEBUG)
bool Object::IsZoneHandle() const {
  return VMHandles::IsZoneHandle(reinterpret_cast<uword>(this));
}

bool Object::IsReadOnlyHandle() const {
  return Dart::IsReadOnlyHandle(reinterpret_cast<uword>(this));
}

bool Object::IsNotTemporaryScopedHandle() const {
  return (IsZoneHandle() || IsReadOnlyHandle());
}
#endif

ObjectPtr Object::Clone(const Object& orig,
                        Heap::Space space,
                        bool load_with_relaxed_atomics) {
  ASSERT(orig.ptr()->IsHeapObject());
  // Generic function types should be cloned with FunctionType::Clone.
  ASSERT(!orig.IsFunctionType() || !FunctionType::Cast(orig).IsGeneric());
  const Class& cls = Class::Handle(orig.clazz());
  intptr_t size = orig.ptr()->untag()->HeapSize();
  // All fields (including non-SmiPtr fields) will be initialized with Smi 0,
  // but the contents of the original object are copied over before the thread
  // is allowed to reach a safepoint.
  ObjectPtr raw_clone =
      Object::Allocate(cls.id(), size, space, cls.HasCompressedPointers(),
                       from_offset<Object>(), to_offset<Object>());
  NoSafepointScope no_safepoint;
  // Copy the body of the original into the clone.
  uword orig_addr = UntaggedObject::ToAddr(orig.ptr());
  uword clone_addr = UntaggedObject::ToAddr(raw_clone);
  const intptr_t kHeaderSizeInBytes = sizeof(UntaggedObject);
  if (load_with_relaxed_atomics) {
    auto orig_atomics_ptr = reinterpret_cast<std::atomic<uword>*>(orig_addr);
    auto clone_ptr = reinterpret_cast<uword*>(clone_addr);
    for (intptr_t i = kHeaderSizeInBytes / kWordSize; i < size / kWordSize;
         i++) {
      *(clone_ptr + i) =
          (orig_atomics_ptr + i)->load(std::memory_order_relaxed);
    }
  } else {
    memmove(reinterpret_cast<uint8_t*>(clone_addr + kHeaderSizeInBytes),
            reinterpret_cast<uint8_t*>(orig_addr + kHeaderSizeInBytes),
            size - kHeaderSizeInBytes);
  }

  if (IsTypedDataClassId(raw_clone->GetClassIdOfHeapObject())) {
    auto raw_typed_data = TypedData::RawCast(raw_clone);
    raw_typed_data.untag()->RecomputeDataField();
  }

  // Add clone to store buffer, if needed.
  if (!raw_clone->IsOldObject()) {
    // No need to remember an object in new space.
    return raw_clone;
  }
  WriteBarrierUpdateVisitor visitor(Thread::Current(), raw_clone);
  raw_clone->untag()->VisitPointers(&visitor);
  return raw_clone;
}

bool Class::HasCompressedPointers() const {
  const intptr_t cid = id();
  switch (cid) {
    case kByteBufferCid:
      return ByteBuffer::ContainsCompressedPointers();
#define HANDLE_CASE(clazz)                                                     \
  case k##clazz##Cid:                                                          \
    return dart::clazz::ContainsCompressedPointers();
      CLASS_LIST(HANDLE_CASE)
#undef HANDLE_CASE
#define HANDLE_CASE(clazz)                                                     \
  case kTypedData##clazz##Cid:                                                 \
    return dart::TypedData::ContainsCompressedPointers();                      \
  case kTypedData##clazz##ViewCid:                                             \
  case kUnmodifiableTypedData##clazz##ViewCid:                                 \
    return dart::TypedDataView::ContainsCompressedPointers();                  \
  case kExternalTypedData##clazz##Cid:                                         \
    return dart::ExternalTypedData::ContainsCompressedPointers();
      CLASS_LIST_TYPED_DATA(HANDLE_CASE)
#undef HANDLE_CASE
    default:
      if (cid >= kNumPredefinedCids) {
        return dart::Instance::ContainsCompressedPointers();
      }
  }
  FATAL("Unsupported class for compressed pointers translation: %s (id=%" Pd
        ", kNumPredefinedCids=%" Pd ")\n",
        ToCString(), cid, kNumPredefinedCids);
  return false;
}

StringPtr Class::Name() const {
  return untag()->name();
}

StringPtr Class::ScrubbedName() const {
  return Symbols::New(Thread::Current(), ScrubbedNameCString());
}

const char* Class::ScrubbedNameCString() const {
  return String::ScrubName(String::Handle(Name()));
}

StringPtr Class::UserVisibleName() const {
#if !defined(PRODUCT)
  ASSERT(untag()->user_name() != String::null());
  return untag()->user_name();
#endif  // !defined(PRODUCT)
  // No caching in PRODUCT, regenerate.
  return Symbols::New(Thread::Current(), GenerateUserVisibleName());
}

const char* Class::UserVisibleNameCString() const {
#if !defined(PRODUCT)
  ASSERT(untag()->user_name() != String::null());
  return String::Handle(untag()->user_name()).ToCString();
#endif                               // !defined(PRODUCT)
  return GenerateUserVisibleName();  // No caching in PRODUCT, regenerate.
}

const char* Class::NameCString(NameVisibility name_visibility) const {
  switch (name_visibility) {
    case Object::kInternalName:
      return String::Handle(Name()).ToCString();
    case Object::kScrubbedName:
      return ScrubbedNameCString();
    case Object::kUserVisibleName:
      return UserVisibleNameCString();
    default:
      UNREACHABLE();
      return nullptr;
  }
}

ClassPtr Class::Mixin() const {
  if (is_transformed_mixin_application()) {
    const Array& interfaces = Array::Handle(this->interfaces());
    ASSERT(interfaces.Length() > 0);
    const Type& mixin_type =
        Type::Handle(Type::RawCast(interfaces.At(interfaces.Length() - 1)));
    return mixin_type.type_class();
  }
  return ptr();
}

bool Class::IsInFullSnapshot() const {
  NoSafepointScope no_safepoint;
  return UntaggedLibrary::InFullSnapshotBit::decode(
      untag()->library()->untag()->flags_);
}

TypePtr Class::RareType() const {
  if (!IsGeneric()) {
    return DeclarationType();
  }
  ASSERT(is_declaration_loaded());
  Thread* const thread = Thread::Current();
  Zone* const zone = thread->zone();
  const auto& inst_to_bounds =
      TypeArguments::Handle(zone, DefaultTypeArguments(zone));
  ASSERT(inst_to_bounds.ptr() != Object::empty_type_arguments().ptr());
  auto& type = Type::Handle(
      zone, Type::New(*this, inst_to_bounds, Nullability::kNonNullable));
  type ^= ClassFinalizer::FinalizeType(type);
  return type.ptr();
}

template <class FakeObject, class TargetFakeObject>
ClassPtr Class::New(IsolateGroup* isolate_group, bool register_class) {
  ASSERT(Object::class_class() != Class::null());
  const auto& result = Class::Handle(Object::Allocate<Class>(Heap::kOld));
  Object::VerifyBuiltinVtable<FakeObject>(FakeObject::kClassId);
  NOT_IN_PRECOMPILED(result.set_token_pos(TokenPosition::kNoSource));
  NOT_IN_PRECOMPILED(result.set_end_token_pos(TokenPosition::kNoSource));
  result.set_instance_size(FakeObject::InstanceSize(),
                           compiler::target::RoundedAllocationSize(
                               TargetFakeObject::InstanceSize()));
  result.set_type_arguments_field_offset_in_words(kNoTypeArguments,
                                                  RTN::Class::kNoTypeArguments);
  const intptr_t host_next_field_offset = FakeObject::NextFieldOffset();
  const intptr_t target_next_field_offset = TargetFakeObject::NextFieldOffset();
  result.set_next_field_offset(host_next_field_offset,
                               target_next_field_offset);
  COMPILE_ASSERT((FakeObject::kClassId != kInstanceCid));
  result.set_id(FakeObject::kClassId);
  NOT_IN_PRECOMPILED(result.set_implementor_cid(kIllegalCid));
  result.set_num_type_arguments_unsafe(0);
  result.set_num_native_fields(0);
  result.set_state_bits(0);
  if (IsInternalOnlyClassId(FakeObject::kClassId) ||
      (FakeObject::kClassId == kTypeArgumentsCid)) {
    // VM internal classes are done. There is no finalization needed or
    // possible in this case.
    result.set_is_declaration_loaded();
    result.set_is_type_finalized();
    result.set_is_allocate_finalized();
  } else if (FakeObject::kClassId != kClosureCid) {
    // VM backed classes are almost ready: run checks and resolve class
    // references, but do not recompute size.
    result.set_is_prefinalized();
  }
  if (FakeObject::kClassId < kNumPredefinedCids &&
      IsDeeplyImmutableCid(FakeObject::kClassId)) {
    result.set_is_deeply_immutable(true);
  }
  NOT_IN_PRECOMPILED(result.set_kernel_offset(0));
  result.InitEmptyFields();
  if (register_class) {
    isolate_group->class_table()->Register(result);
  }
  return result.ptr();
}

#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES)
static void ReportTooManyTypeArguments(const Class& cls) {
  Report::MessageF(Report::kError, Script::Handle(cls.script()),
                   cls.token_pos(), Report::AtLocation,
                   "too many type parameters declared in class '%s' or in its "
                   "super classes",
                   String::Handle(cls.Name()).ToCString());
  UNREACHABLE();
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES)

void Class::set_num_type_arguments(intptr_t value) const {
#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES)
  UNREACHABLE();
#else
  if (!Utils::IsInt(16, value)) {
    ReportTooManyTypeArguments(*this);
  }
  // We allow concurrent calculation of the number of type arguments. If two
  // threads perform this operation it doesn't matter which one wins.
  DEBUG_ONLY(intptr_t old_value = num_type_arguments());
  DEBUG_ASSERT(old_value == kUnknownNumTypeArguments || old_value == value);
  StoreNonPointer<int16_t, int16_t, std::memory_order_relaxed>(
      &untag()->num_type_arguments_, value);
#endif  // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES)
}

void Class::set_num_type_arguments_unsafe(intptr_t value) const {
  StoreNonPointer(&untag()->num_type_arguments_, value);
}

void Class::set_has_pragma(bool value) const {
  set_state_bits(HasPragmaBit::update(value, state_bits()));
}

void Class::set_is_isolate_unsendable(bool value) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(IsIsolateUnsendableBit::update(value, state_bits()));
}

void Class::set_is_isolate_unsendable_due_to_pragma(bool value) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(
      IsIsolateUnsendableDueToPragmaBit::update(value, state_bits()));
}

void Class::set_is_deeply_immutable(bool value) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(IsDeeplyImmutableBit::update(value, state_bits()));
}

void Class::set_is_future_subtype(bool value) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(IsFutureSubtypeBit::update(value, state_bits()));
}

void Class::set_can_be_future(bool value) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(CanBeFutureBit::update(value, state_bits()));
}

void Class::set_has_dynamically_extendable_subtypes(bool value) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(
      HasDynamicallyExtendableSubtypesBit::update(value, state_bits()));
}

// Initialize class fields of type Array with empty array.
void Class::InitEmptyFields() const {
  if (Object::empty_array().ptr() == Array::null()) {
    // The empty array has not been initialized yet.
    return;
  }
  untag()->set_interfaces(Object::empty_array().ptr());
  untag()->set_constants(Object::null_array().ptr());
  set_functions(Object::empty_array());
  set_fields(Object::empty_array());
  set_invocation_dispatcher_cache(Object::empty_array());
}

ArrayPtr Class::OffsetToFieldMap(
    ClassTable* class_table /* = nullptr */) const {
  ASSERT(is_finalized());
  if (untag()->offset_in_words_to_field<std::memory_order_acquire>() ==
      Array::null()) {
    // Even if multiple threads are calling this concurrently, all of them would
    // compute the same array, so we intentionally don't acquire any locks here.
    const intptr_t length = untag()->host_instance_size_in_words_;
    const Array& array = Array::Handle(Array::New(length, Heap::kOld));
    Class& cls = Class::Handle(this->ptr());
    Array& fields = Array::Handle();
    Field& f = Field::Handle();
    while (!cls.IsNull()) {
      fields = cls.fields();
      for (intptr_t i = 0; i < fields.Length(); ++i) {
        f ^= fields.At(i);
        if (f.is_instance()) {
          array.SetAt(f.HostOffset() >> kCompressedWordSizeLog2, f);
        }
      }
      cls = cls.SuperClass(class_table);
    }
    untag()->set_offset_in_words_to_field<std::memory_order_release>(
        array.ptr());
  }
  return untag()->offset_in_words_to_field<std::memory_order_acquire>();
}

bool Class::HasInstanceFields() const {
  const Array& field_array = Array::Handle(fields());
  Field& field = Field::Handle();
  for (intptr_t i = 0; i < field_array.Length(); ++i) {
    field ^= field_array.At(i);
    if (!field.is_static()) {
      return true;
    }
  }
  return false;
}

class FunctionName {
 public:
  FunctionName(const String& name, String* tmp_string)
      : name_(name), tmp_string_(tmp_string) {}
  bool Matches(const Function& function) const {
    if (name_.IsSymbol()) {
      return name_.ptr() == function.name();
    } else {
      *tmp_string_ = function.name();
      return name_.Equals(*tmp_string_);
    }
  }
  intptr_t Hash() const { return name_.Hash(); }

 private:
  const String& name_;
  String* tmp_string_;
};

// Traits for looking up Functions by name.
class ClassFunctionsTraits {
 public:
  static const char* Name() { return "ClassFunctionsTraits"; }
  static bool ReportStats() { return false; }

  // Called when growing the table.
  static bool IsMatch(const Object& a, const Object& b) {
    ASSERT(a.IsFunction() && b.IsFunction());
    // Function objects are always canonical.
    return a.ptr() == b.ptr();
  }
  static bool IsMatch(const FunctionName& name, const Object& obj) {
    return name.Matches(Function::Cast(obj));
  }
  static uword Hash(const Object& key) {
    return String::HashRawSymbol(Function::Cast(key).name());
  }
  static uword Hash(const FunctionName& name) { return name.Hash(); }
};
typedef UnorderedHashSet<ClassFunctionsTraits> ClassFunctionsSet;

void Class::SetFunctions(const Array& value) const {
  ASSERT(!value.IsNull());
  const intptr_t len = value.Length();
#if defined(DEBUG)
  Thread* thread = Thread::Current();
  ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
  if (is_finalized()) {
    Function& function = Function::Handle();
    FunctionType& signature = FunctionType::Handle();
    for (intptr_t i = 0; i < len; ++i) {
      function ^= value.At(i);
      signature = function.signature();
      ASSERT(signature.IsFinalized());
    }
  }
#endif
  set_functions(value);
  if (len >= kFunctionLookupHashThreshold) {
    ClassFunctionsSet set(HashTables::New<ClassFunctionsSet>(len, Heap::kOld));
    Function& func = Function::Handle();
    for (intptr_t i = 0; i < len; ++i) {
      func ^= value.At(i);
      // Verify that all the functions in the array have this class as owner.
      ASSERT(func.Owner() == ptr());
      set.Insert(func);
    }
    untag()->set_functions_hash_table(set.Release().ptr());
  } else {
    untag()->set_functions_hash_table(Array::null());
  }
}

void Class::AddFunction(const Function& function) const {
#if defined(DEBUG)
  Thread* thread = Thread::Current();
  ASSERT(thread->IsDartMutatorThread());
  ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
  ASSERT(!is_finalized() ||
         FunctionType::Handle(function.signature()).IsFinalized());
#endif
  const Array& arr = Array::Handle(functions());
  const Array& new_array =
      Array::Handle(Array::Grow(arr, arr.Length() + 1, Heap::kOld));
  new_array.SetAt(arr.Length(), function);
  set_functions(new_array);
  // Add to hash table, if any.
  const intptr_t new_len = new_array.Length();
  if (new_len == kFunctionLookupHashThreshold) {
    // Transition to using hash table.
    SetFunctions(new_array);
  } else if (new_len > kFunctionLookupHashThreshold) {
    ClassFunctionsSet set(untag()->functions_hash_table());
    set.Insert(function);
    untag()->set_functions_hash_table(set.Release().ptr());
  }
}

intptr_t Class::FindFunctionIndex(const Function& needle) const {
  Thread* thread = Thread::Current();
  if (EnsureIsFinalized(thread) != Error::null()) {
    return -1;
  }
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_FUNCTION_HANDLESCOPE(thread);
  Array& funcs = thread->ArrayHandle();
  Function& function = thread->FunctionHandle();
  funcs = current_functions();
  ASSERT(!funcs.IsNull());
  const intptr_t len = funcs.Length();
  for (intptr_t i = 0; i < len; i++) {
    function ^= funcs.At(i);
    if (needle.ptr() == function.ptr()) {
      return i;
    }
  }
  // No function found.
  return -1;
}

FunctionPtr Class::FunctionFromIndex(intptr_t idx) const {
  const Array& funcs = Array::Handle(current_functions());
  if ((idx < 0) || (idx >= funcs.Length())) {
    return Function::null();
  }
  Function& func = Function::Handle();
  func ^= funcs.At(idx);
  ASSERT(!func.IsNull());
  return func.ptr();
}

FunctionPtr Class::ImplicitClosureFunctionFromIndex(intptr_t idx) const {
  Function& func = Function::Handle(FunctionFromIndex(idx));
  if (func.IsNull() || !func.HasImplicitClosureFunction()) {
    return Function::null();
  }
  func = func.ImplicitClosureFunction();
  ASSERT(!func.IsNull());
  return func.ptr();
}

intptr_t Class::FindImplicitClosureFunctionIndex(const Function& needle) const {
  Thread* thread = Thread::Current();
  if (EnsureIsFinalized(thread) != Error::null()) {
    return -1;
  }
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_FUNCTION_HANDLESCOPE(thread);
  Array& funcs = thread->ArrayHandle();
  Function& function = thread->FunctionHandle();
  funcs = current_functions();
  ASSERT(!funcs.IsNull());
  Function& implicit_closure = Function::Handle(thread->zone());
  const intptr_t len = funcs.Length();
  for (intptr_t i = 0; i < len; i++) {
    function ^= funcs.At(i);
    implicit_closure = function.implicit_closure_function();
    if (implicit_closure.IsNull()) {
      // Skip non-implicit closure functions.
      continue;
    }
    if (needle.ptr() == implicit_closure.ptr()) {
      return i;
    }
  }
  // No function found.
  return -1;
}

intptr_t Class::FindInvocationDispatcherFunctionIndex(
    const Function& needle) const {
  Thread* thread = Thread::Current();
  if (EnsureIsFinalized(thread) != Error::null()) {
    return -1;
  }
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_OBJECT_HANDLESCOPE(thread);
  Array& funcs = thread->ArrayHandle();
  Object& object = thread->ObjectHandle();
  funcs = invocation_dispatcher_cache();
  ASSERT(!funcs.IsNull());
  const intptr_t len = funcs.Length();
  for (intptr_t i = 0; i < len; i++) {
    object = funcs.At(i);
    // The invocation_dispatcher_cache is a table with some entries that
    // are functions.
    if (object.IsFunction()) {
      if (Function::Cast(object).ptr() == needle.ptr()) {
        return i;
      }
    }
  }
  // No function found.
  return -1;
}

FunctionPtr Class::InvocationDispatcherFunctionFromIndex(intptr_t idx) const {
  Thread* thread = Thread::Current();
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_OBJECT_HANDLESCOPE(thread);
  Array& dispatcher_cache = thread->ArrayHandle();
  Object& object = thread->ObjectHandle();
  dispatcher_cache = invocation_dispatcher_cache();
  object = dispatcher_cache.At(idx);
  if (!object.IsFunction()) {
    return Function::null();
  }
  return Function::Cast(object).ptr();
}

void Class::set_state_bits(intptr_t bits) const {
  StoreNonPointer<uint32_t, uint32_t, std::memory_order_release>(
      &untag()->state_bits_, static_cast<uint32_t>(bits));
}

void Class::set_library(const Library& value) const {
  untag()->set_library(value.ptr());
}

void Class::set_type_parameters(const TypeParameters& value) const {
  ASSERT((num_type_arguments() == kUnknownNumTypeArguments) ||
         is_declared_in_bytecode() || is_prefinalized());
  untag()->set_type_parameters(value.ptr());
}

void Class::set_functions(const Array& value) const {
  // Ensure all writes to the [Function]s are visible by the time the array
  // is visible.
  untag()->set_functions<std::memory_order_release>(value.ptr());
}

void Class::set_fields(const Array& value) const {
  // Ensure all writes to the [Field]s are visible by the time the array
  // is visible.
  untag()->set_fields<std::memory_order_release>(value.ptr());
}

void Class::set_invocation_dispatcher_cache(const Array& cache) const {
  // Ensure all writes to the cache are visible by the time the array
  // is visible.
  untag()->set_invocation_dispatcher_cache<std::memory_order_release>(
      cache.ptr());
}

void Class::set_declaration_instance_type_arguments(
    const TypeArguments& value) const {
  ASSERT(value.IsNull() || (value.IsCanonical() && value.IsOld()));
  ASSERT((declaration_instance_type_arguments() == TypeArguments::null()) ||
         (declaration_instance_type_arguments() == value.ptr()));
  untag()->set_declaration_instance_type_arguments<std::memory_order_release>(
      value.ptr());
}

TypeArgumentsPtr Class::GetDeclarationInstanceTypeArguments() const {
  const intptr_t num_type_arguments = NumTypeArguments();
  if (num_type_arguments == 0) {
    return TypeArguments::null();
  }
  if (declaration_instance_type_arguments() != TypeArguments::null()) {
    return declaration_instance_type_arguments();
  }
  Thread* thread = Thread::Current();
  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
  if (declaration_instance_type_arguments() != TypeArguments::null()) {
    return declaration_instance_type_arguments();
  }
  Zone* zone = thread->zone();
  auto& args = TypeArguments::Handle(zone);
  auto& type = AbstractType::Handle(zone);
  const intptr_t num_type_parameters = NumTypeParameters(thread);
  if (num_type_arguments == num_type_parameters) {
    type = DeclarationType();
    args = Type::Cast(type).arguments();
  } else {
    type = super_type();
    const auto& super_args = TypeArguments::Handle(
        zone, Type::Cast(type).GetInstanceTypeArguments(thread));
    if ((num_type_parameters == 0) ||
        (!super_args.IsNull() && (super_args.Length() == num_type_arguments))) {
      args = super_args.ptr();
    } else {
      args = TypeArguments::New(num_type_arguments);
      const intptr_t offset = num_type_arguments - num_type_parameters;
      for (intptr_t i = 0; i < offset; ++i) {
        type = super_args.TypeAtNullSafe(i);
        args.SetTypeAt(i, type);
      }
      type = DeclarationType();
      const auto& decl_args =
          TypeArguments::Handle(zone, Type::Cast(type).arguments());
      for (intptr_t i = 0; i < num_type_parameters; ++i) {
        type = decl_args.TypeAt(i);
        args.SetTypeAt(offset + i, type);
      }
    }
  }
  args = args.Canonicalize(thread);
  set_declaration_instance_type_arguments(args);
  return args.ptr();
}

TypeArgumentsPtr Class::GetInstanceTypeArguments(
    Thread* thread,
    const TypeArguments& type_arguments,
    bool canonicalize) const {
  const intptr_t num_type_arguments = NumTypeArguments();
  if (num_type_arguments == 0) {
    return TypeArguments::null();
  }
  Zone* zone = thread->zone();
  auto& args = TypeArguments::Handle(zone);
  const intptr_t num_type_parameters = NumTypeParameters(thread);
  ASSERT(type_arguments.IsNull() ||
         type_arguments.Length() == num_type_parameters);
  if (num_type_arguments == num_type_parameters) {
    args = type_arguments.ptr();
  } else {
    args = GetDeclarationInstanceTypeArguments();
    if (num_type_parameters == 0) {
      return args.ptr();
    }
    args = args.InstantiateFrom(
        TypeArguments::Handle(
            zone, type_arguments.ToInstantiatorTypeArguments(thread, *this)),
        Object::null_type_arguments(), kAllFree, Heap::kOld);
  }
  if (canonicalize) {
    args = args.Canonicalize(thread);
  }
  return args.ptr();
}

intptr_t Class::NumTypeParameters(Thread* thread) const {
  if (!is_declaration_loaded()) {
    ASSERT(is_prefinalized());
    const intptr_t cid = id();
    if ((cid == kArrayCid) || (cid == kImmutableArrayCid) ||
        (cid == kGrowableObjectArrayCid)) {
      return 1;  // List's type parameter may not have been parsed yet.
    }
    return 0;
  }
  if (type_parameters() == TypeParameters::null()) {
    return 0;
  }
  REUSABLE_TYPE_PARAMETERS_HANDLESCOPE(thread);
  TypeParameters& type_params = thread->TypeParametersHandle();
  type_params = type_parameters();
  return type_params.Length();
}

intptr_t Class::ComputeNumTypeArguments() const {
  ASSERT(is_declaration_loaded());
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  auto isolate_group = thread->isolate_group();
  const intptr_t num_type_params = NumTypeParameters();

  if ((super_type() == AbstractType::null()) ||
      (super_type() == isolate_group->object_store()->object_type())) {
    return num_type_params;
  }

  const auto& sup_type = Type::Handle(zone, super_type());
  const auto& sup_class = Class::Handle(zone, sup_type.type_class());
  const intptr_t sup_class_num_type_args = sup_class.NumTypeArguments();
  if (num_type_params == 0) {
    return sup_class_num_type_args;
  }

  const auto& sup_type_args = TypeArguments::Handle(zone, sup_type.arguments());
  if (sup_type_args.IsNull()) {
    // The super type is raw or the super class is non generic.
    // In either case, overlapping is not possible.
    return sup_class_num_type_args + num_type_params;
  }

  const intptr_t sup_type_args_length = sup_type_args.Length();
  // Determine the maximum overlap of a prefix of the vector consisting of the
  // type parameters of this class with a suffix of the vector consisting of the
  // type arguments of the super type of this class.
  // The number of own type arguments of this class is the number of its type
  // parameters minus the number of type arguments in the overlap.
  // Attempt to overlap the whole vector of type parameters; reduce the size
  // of the vector (keeping the first type parameter) until it fits or until
  // its size is zero.
  auto& sup_type_arg = AbstractType::Handle(zone);
  for (intptr_t num_overlapping_type_args =
           (num_type_params < sup_type_args_length) ? num_type_params
                                                    : sup_type_args_length;
       num_overlapping_type_args > 0; num_overlapping_type_args--) {
    intptr_t i = 0;
    for (; i < num_overlapping_type_args; i++) {
      sup_type_arg = sup_type_args.TypeAt(sup_type_args_length -
                                          num_overlapping_type_args + i);
      ASSERT(!sup_type_arg.IsNull());
      if (!sup_type_arg.IsTypeParameter()) break;
      // The only type parameters appearing in the type arguments of the super
      // type are those declared by this class. Their finalized indices depend
      // on the number of type arguments being computed here. Therefore, they
      // cannot possibly be finalized yet.
      ASSERT(!TypeParameter::Cast(sup_type_arg).IsFinalized());
      if (TypeParameter::Cast(sup_type_arg).index() != i ||
          TypeParameter::Cast(sup_type_arg).IsNullable()) {
        break;
      }
    }
    if (i == num_overlapping_type_args) {
      // Overlap found.
      return sup_class_num_type_args + num_type_params -
             num_overlapping_type_args;
    }
  }
  // No overlap found.
  return sup_class_num_type_args + num_type_params;
}

intptr_t Class::NumTypeArguments() const {
  // Return cached value if already calculated.
  intptr_t num_type_args = num_type_arguments();
  if (num_type_args != kUnknownNumTypeArguments) {
    return num_type_args;
  }

#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
  return 0;
#else
  num_type_args = ComputeNumTypeArguments();
  ASSERT(num_type_args != kUnknownNumTypeArguments);
  set_num_type_arguments(num_type_args);
  return num_type_args;
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

TypeArgumentsPtr Class::DefaultTypeArguments(Zone* zone) const {
  if (type_parameters() == TypeParameters::null()) {
    return Object::empty_type_arguments().ptr();
  }
  return TypeParameters::Handle(zone, type_parameters()).defaults();
}

ClassPtr Class::SuperClass(ClassTable* class_table /* = nullptr */) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  if (class_table == nullptr) {
    class_table = thread->isolate_group()->class_table();
  }

  if (super_type() == AbstractType::null()) {
    if (id() == kTypeArgumentsCid) {
      // Pretend TypeArguments objects are Dart instances.
      return class_table->At(kInstanceCid);
    }
    return Class::null();
  }
  const AbstractType& sup_type = AbstractType::Handle(zone, super_type());
  const intptr_t type_class_id = sup_type.type_class_id();
  return class_table->At(type_class_id);
}

void Class::set_super_type(const Type& value) const {
  ASSERT(value.IsNull() || !value.IsDynamicType());
  untag()->set_super_type(value.ptr());
}

TypeParameterPtr Class::TypeParameterAt(intptr_t index,
                                        Nullability nullability) const {
  ASSERT(index >= 0 && index < NumTypeParameters());
  TypeParameter& type_param =
      TypeParameter::Handle(TypeParameter::New(*this, 0, index, nullability));
  // Finalize type parameter only if its declaring class is
  // finalized and available in the current class table.
  if (is_type_finalized() && (type_param.parameterized_class() == ptr())) {
    type_param ^= ClassFinalizer::FinalizeType(type_param);
  }
  return type_param.ptr();
}

intptr_t Class::UnboxedFieldSizeInBytesByCid(intptr_t cid) {
  switch (cid) {
    case kDoubleCid:
      return sizeof(UntaggedDouble::value_);
    case kFloat32x4Cid:
      return sizeof(UntaggedFloat32x4::value_);
    case kFloat64x2Cid:
      return sizeof(UntaggedFloat64x2::value_);
    default:
      return sizeof(UntaggedMint::value_);
  }
}

UnboxedFieldBitmap Class::CalculateFieldOffsets() const {
  Array& flds = Array::Handle(fields());
  const Class& super = Class::Handle(SuperClass());
  intptr_t host_offset = 0;
  UnboxedFieldBitmap host_bitmap{};
  // Target offsets might differ if the word size are different
  intptr_t target_offset = 0;
  intptr_t host_type_args_field_offset = kNoTypeArguments;
  intptr_t target_type_args_field_offset = RTN::Class::kNoTypeArguments;
  if (super.IsNull()) {
    host_offset = Instance::NextFieldOffset();
    target_offset = RTN::Instance::NextFieldOffset();
    ASSERT(host_offset > 0);
    ASSERT(target_offset > 0);
  } else {
    ASSERT(super.is_finalized() || super.is_prefinalized());
    host_type_args_field_offset = super.host_type_arguments_field_offset();
    target_type_args_field_offset = super.target_type_arguments_field_offset();
    host_offset = super.host_next_field_offset();
    ASSERT(host_offset > 0);
    target_offset = super.target_next_field_offset();
    ASSERT(target_offset > 0);
    // We should never call CalculateFieldOffsets for native wrapper
    // classes, assert this.
    ASSERT(num_native_fields() == 0);
    const intptr_t num_native_fields = super.num_native_fields();
    set_num_native_fields(num_native_fields);
    if (num_native_fields > 0 || is_isolate_unsendable_due_to_pragma()) {
      set_is_isolate_unsendable(true);
    }

    host_bitmap = IsolateGroup::Current()->class_table()->GetUnboxedFieldsMapAt(
        super.id());
  }
  // If the super class is parameterized, use the same type_arguments field,
  // otherwise, if this class is the first in the super chain to be
  // parameterized, introduce a new type_arguments field.
  if (host_type_args_field_offset == kNoTypeArguments) {
    ASSERT(target_type_args_field_offset == RTN::Class::kNoTypeArguments);
    if (IsGeneric()) {
      // The instance needs a type_arguments field.
      host_type_args_field_offset = host_offset;
      target_type_args_field_offset = target_offset;
      host_offset += kCompressedWordSize;
      target_offset += compiler::target::kCompressedWordSize;
    }
  } else {
    ASSERT(target_type_args_field_offset != RTN::Class::kNoTypeArguments);
  }

  set_type_arguments_field_offset(host_type_args_field_offset,
                                  target_type_args_field_offset);
  ASSERT(host_offset > 0);
  ASSERT(target_offset > 0);
  Field& field = Field::Handle();
  const intptr_t len = flds.Length();
  for (intptr_t i = 0; i < len; i++) {
    field ^= flds.At(i);
    // Offset is computed only for instance fields.
    if (!field.is_static()) {
      ASSERT(field.HostOffset() == 0);
      ASSERT(field.TargetOffset() == 0);
      field.SetOffset(host_offset, target_offset);

      if (field.is_unboxed()) {
        const intptr_t field_size =
            UnboxedFieldSizeInBytesByCid(field.guarded_cid());

        const intptr_t host_num_words = field_size / kCompressedWordSize;
        const intptr_t host_next_offset = host_offset + field_size;
        const intptr_t host_next_position =
            host_next_offset / kCompressedWordSize;

        const intptr_t target_next_offset = target_offset + field_size;
        const intptr_t target_next_position =
            target_next_offset / compiler::target::kCompressedWordSize;

        // The bitmap has fixed length. Checks if the offset position is smaller
        // than its length. If it is not, than the field should be boxed
        if (host_next_position <= UnboxedFieldBitmap::Length() &&
            target_next_position <= UnboxedFieldBitmap::Length()) {
          for (intptr_t j = 0; j < host_num_words; j++) {
            // Activate the respective bit in the bitmap, indicating that the
            // content is not a pointer
            host_bitmap.Set(host_offset / kCompressedWordSize);
            host_offset += kCompressedWordSize;
          }

          ASSERT(host_offset == host_next_offset);
          target_offset = target_next_offset;
        } else {
          // Make the field boxed
          field.set_is_unboxed(false);
          host_offset += kCompressedWordSize;
          target_offset += compiler::target::kCompressedWordSize;
        }
      } else {
        host_offset += kCompressedWordSize;
        target_offset += compiler::target::kCompressedWordSize;
      }
    }
  }

  const intptr_t host_instance_size = RoundedAllocationSize(host_offset);
  const intptr_t target_instance_size =
      compiler::target::RoundedAllocationSize(target_offset);
  if (!Utils::IsInt(32, target_instance_size)) {
    // Many parts of the compiler assume offsets can be represented with
    // int32_t.
    FATAL("Too many fields in %s\n", UserVisibleNameCString());
  }
  set_instance_size(host_instance_size, target_instance_size);
  set_next_field_offset(host_offset, target_offset);
  return host_bitmap;
}

void Class::AddInvocationDispatcher(const String& target_name,
                                    const Array& args_desc,
                                    const Function& dispatcher) const {
  auto thread = Thread::Current();
  ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());

  ASSERT(target_name.ptr() == dispatcher.name());

  DispatcherSet dispatchers(invocation_dispatcher_cache() ==
                                    Array::empty_array().ptr()
                                ? HashTables::New<DispatcherSet>(4, Heap::kOld)
                                : invocation_dispatcher_cache());
  dispatchers.Insert(dispatcher);
  set_invocation_dispatcher_cache(dispatchers.Release());
}

FunctionPtr Class::GetInvocationDispatcher(const String& target_name,
                                           const Array& args_desc,
                                           UntaggedFunction::Kind kind,
                                           bool create_if_absent) const {
  ASSERT(kind == UntaggedFunction::kNoSuchMethodDispatcher ||
         kind == UntaggedFunction::kInvokeFieldDispatcher ||
         kind == UntaggedFunction::kDynamicInvocationForwarder);
  auto thread = Thread::Current();
  auto Z = thread->zone();
  auto& function = Function::Handle(Z);

  // First we'll try to find it without using locks.
  DispatcherKey key(target_name, args_desc, kind);
  if (invocation_dispatcher_cache() != Array::empty_array().ptr()) {
    DispatcherSet dispatchers(Z, invocation_dispatcher_cache());
    function ^= dispatchers.GetOrNull(key);
    dispatchers.Release();
  }
  if (!function.IsNull() || !create_if_absent) {
    return function.ptr();
  }

  // If we failed to find it and possibly need to create it, use a write lock.
  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());

  // Try to find it again & return if it was added in the meantime.
  if (invocation_dispatcher_cache() != Array::empty_array().ptr()) {
    DispatcherSet dispatchers(Z, invocation_dispatcher_cache());
    function ^= dispatchers.GetOrNull(key);
    dispatchers.Release();
  }
  if (!function.IsNull()) return function.ptr();

  // Otherwise create it & add it.
  function = CreateInvocationDispatcher(target_name, args_desc, kind);
  AddInvocationDispatcher(target_name, args_desc, function);
  return function.ptr();
}

FunctionPtr Class::CreateInvocationDispatcher(
    const String& target_name,
    const Array& args_desc,
    UntaggedFunction::Kind kind) const {
  ASSERT(target_name.ptr() != Symbols::DynamicImplicitCall().ptr());
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  FunctionType& signature = FunctionType::Handle(zone, FunctionType::New());
  Function& invocation = Function::Handle(
      zone, Function::New(
                signature,
                String::Handle(zone, Symbols::New(thread, target_name)), kind,
                false,  // Not static.
                false,  // Not const.
                false,  // Not abstract.
                false,  // Not external.
                false,  // Not native.
                *this, TokenPosition::kMinSource));
  ArgumentsDescriptor desc(args_desc);
  const intptr_t type_args_len = desc.TypeArgsLen();
  if (type_args_len > 0) {
    // Make dispatcher function generic, since type arguments are passed.
    const auto& type_parameters =
        TypeParameters::Handle(zone, TypeParameters::New(type_args_len));
    // Allow any type, as any type checking is compiled into the dispatcher.
    auto& bound = Type::Handle(
        zone, IsolateGroup::Current()->object_store()->nullable_object_type());
    for (intptr_t i = 0; i < type_args_len; i++) {
      // The name of the type parameter does not matter, as a type error using
      // it should never be thrown.
      type_parameters.SetNameAt(i, Symbols::OptimizedOut());
      type_parameters.SetBoundAt(i, bound);
      // Type arguments will always be provided, so the default is not used.
      type_parameters.SetDefaultAt(i, Object::dynamic_type());
    }
    signature.SetTypeParameters(type_parameters);
  }

  signature.set_num_fixed_parameters(desc.PositionalCount());
  signature.SetNumOptionalParameters(desc.NamedCount(),
                                     false);  // Not positional.
  signature.set_parameter_types(
      Array::Handle(zone, Array::New(desc.Count(), Heap::kOld)));
  invocation.CreateNameArray();
  signature.CreateNameArrayIncludingFlags();
  // Receiver.
  signature.SetParameterTypeAt(0, Object::dynamic_type());
  invocation.SetParameterNameAt(0, Symbols::This());
  // Remaining positional parameters.
  for (intptr_t i = 1; i < desc.PositionalCount(); i++) {
    signature.SetParameterTypeAt(i, Object::dynamic_type());
    char name[64];
    Utils::SNPrint(name, 64, ":p%" Pd, i);
    invocation.SetParameterNameAt(
        i, String::Handle(zone, Symbols::New(thread, name)));
  }

  // Named parameters.
  for (intptr_t i = 0; i < desc.NamedCount(); i++) {
    const intptr_t param_index = desc.PositionAt(i);
    const auto& param_name = String::Handle(zone, desc.NameAt(i));
    signature.SetParameterTypeAt(param_index, Object::dynamic_type());
    signature.SetParameterNameAt(param_index, param_name);
  }
  signature.FinalizeNameArray();
  signature.set_result_type(Object::dynamic_type());
  invocation.set_is_debuggable(false);
  invocation.set_is_visible(false);
  invocation.set_is_reflectable(false);
  invocation.set_saved_args_desc(args_desc);

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

#if defined(DART_DYNAMIC_MODULES)
#if defined(DART_PRECOMPILED_RUNTIME)
  const bool attach_bytecode = true;
#else
  const bool attach_bytecode = is_declared_in_bytecode();
#endif
  if (attach_bytecode) {
    switch (kind) {
      case UntaggedFunction::kNoSuchMethodDispatcher:
        invocation.AttachBytecode(Object::nsm_dispatcher_bytecode());
        break;
      case UntaggedFunction::kInvokeFieldDispatcher:
        invocation.AttachBytecode(Object::invoke_field_bytecode());
        break;
      default:
        UNREACHABLE();
    }
  }
#endif  // defined(DART_DYNAMIC_MODULES)

  return invocation.ptr();
}

// Method extractors are used to create implicit closures from methods.
// When an expression obj.M is evaluated for the first time and receiver obj
// does not have a getter called M but has a method called M then an extractor
// is created and injected as a getter (under the name get:M) into the class
// owning method M.
FunctionPtr Function::CreateMethodExtractor(const String& getter_name) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  ASSERT(Field::IsGetterName(getter_name));
  const Function& closure_function =
      Function::Handle(zone, ImplicitClosureFunction());

  const Class& owner = Class::Handle(zone, closure_function.Owner());
  FunctionType& signature = FunctionType::Handle(zone, FunctionType::New());
  const Function& extractor = Function::Handle(
      zone,
      Function::New(signature,
                    String::Handle(zone, Symbols::New(thread, getter_name)),
                    UntaggedFunction::kMethodExtractor,
                    false,  // Not static.
                    false,  // Not const.
                    is_abstract(),
                    false,  // Not external.
                    false,  // Not native.
                    owner, TokenPosition::kMethodExtractor));

  // Initialize signature: receiver is a single fixed parameter.
  const intptr_t kNumParameters = 1;
  signature.set_num_fixed_parameters(kNumParameters);
  signature.SetNumOptionalParameters(0, false);
  signature.set_parameter_types(Object::synthetic_getter_parameter_types());
#if !defined(DART_PRECOMPILED_RUNTIME)
  extractor.set_positional_parameter_names(
      Object::synthetic_getter_parameter_names());
#endif
  signature.set_result_type(Object::dynamic_type());

  extractor.InheritKernelOffsetFrom(*this);

  extractor.set_extracted_method_closure(closure_function);
  extractor.set_is_debuggable(false);
  extractor.set_is_visible(false);
#if !defined(DART_PRECOMPILED_RUNTIME)
  extractor.SetIsDynamicallyOverridden(IsDynamicallyOverridden());
#endif

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

#if defined(DART_DYNAMIC_MODULES)
#if defined(DART_PRECOMPILED_RUNTIME)
  const bool attach_bytecode = true;
#else
  const bool attach_bytecode = is_declared_in_bytecode();
#endif
  if (attach_bytecode) {
    extractor.AttachBytecode(Object::method_extractor_bytecode());
  }
#endif  // defined(DART_DYNAMIC_MODULES)

  owner.AddFunction(extractor);

  return extractor.ptr();
}

FunctionPtr Function::GetMethodExtractor(const String& getter_name) const {
  ASSERT(Field::IsGetterName(getter_name));
  const Function& closure_function =
      Function::Handle(ImplicitClosureFunction());
  const Class& owner = Class::Handle(closure_function.Owner());
  Thread* thread = Thread::Current();
  if (owner.EnsureIsFinalized(thread) != Error::null()) {
    return Function::null();
  }
  IsolateGroup* group = thread->isolate_group();
  Function& result = Function::Handle(
      Resolver::ResolveDynamicFunction(thread->zone(), owner, getter_name));
  if (result.IsNull()) {
    SafepointWriteRwLocker ml(thread, group->program_lock());
    result = owner.LookupDynamicFunctionUnsafe(getter_name);
    if (result.IsNull()) {
      result = CreateMethodExtractor(getter_name);
    }
  }
  ASSERT(result.kind() == UntaggedFunction::kMethodExtractor);
  return result.ptr();
}

// Record field getters are used to access fields of arbitrary
// record instances dynamically.
FunctionPtr Class::CreateRecordFieldGetter(const String& getter_name) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  ASSERT(IsRecordClass());
  ASSERT(Field::IsGetterName(getter_name));
  FunctionType& signature = FunctionType::Handle(zone, FunctionType::New());
  const Function& getter = Function::Handle(
      zone,
      Function::New(signature,
                    String::Handle(zone, Symbols::New(thread, getter_name)),
                    UntaggedFunction::kRecordFieldGetter,
                    false,  // Not static.
                    false,  // Not const.
                    false,  // Not abstract.
                    false,  // Not external.
                    false,  // Not native.
                    *this, TokenPosition::kMinSource));

  // Initialize signature: receiver is a single fixed parameter.
  const intptr_t kNumParameters = 1;
  signature.set_num_fixed_parameters(kNumParameters);
  signature.SetNumOptionalParameters(0, false);
  signature.set_parameter_types(Object::synthetic_getter_parameter_types());
#if !defined(DART_PRECOMPILED_RUNTIME)
  getter.set_positional_parameter_names(
      Object::synthetic_getter_parameter_names());
#endif
  signature.set_result_type(Object::dynamic_type());

  getter.set_is_debuggable(false);
  getter.set_is_visible(false);

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

  AddFunction(getter);

  return getter.ptr();
}

FunctionPtr Class::GetRecordFieldGetter(const String& getter_name) const {
  ASSERT(IsRecordClass());
  ASSERT(Field::IsGetterName(getter_name));
  Thread* thread = Thread::Current();
  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
  Function& result = Function::Handle(thread->zone(),
                                      LookupDynamicFunctionUnsafe(getter_name));
  if (result.IsNull()) {
    result = CreateRecordFieldGetter(getter_name);
  }
  ASSERT(result.kind() == UntaggedFunction::kRecordFieldGetter);
  return result.ptr();
}

bool FindPragmaInMetadata(Thread* T,
                          const Object& metadata_obj,
                          const String& pragma_name,
                          bool multiple,
                          Object* options) {
  auto IG = T->isolate_group();
  auto Z = T->zone();

  // If there is a compile-time error while evaluating the metadata, we will
  // simply claim there was no @pragma annotation.
  if (metadata_obj.IsNull() || metadata_obj.IsLanguageError()) {
    return false;
  }
  ASSERT(metadata_obj.IsArray());

  auto& metadata = Array::Cast(metadata_obj);
  auto& pragma_class = Class::Handle(Z, IG->object_store()->pragma_class());
  if (pragma_class.IsNull()) {
    // Precompiler may drop pragma class.
    return false;
  }
  auto& pragma_name_field =
      Field::Handle(Z, pragma_class.LookupField(Symbols::name()));
  auto& pragma_options_field =
      Field::Handle(Z, pragma_class.LookupField(Symbols::options()));

  auto& pragma = Object::Handle(Z);
  bool found = false;
  auto& options_value = Object::Handle(Z);
  auto& results = GrowableObjectArray::Handle(Z);
  if (multiple) {
    ASSERT(options != nullptr);
    results ^= GrowableObjectArray::New(1);
  }
  for (intptr_t i = 0; i < metadata.Length(); ++i) {
    pragma = metadata.At(i);
    if (pragma.clazz() != pragma_class.ptr() ||
        Instance::Cast(pragma).GetField(pragma_name_field) !=
            pragma_name.ptr()) {
      continue;
    }
    options_value = Instance::Cast(pragma).GetField(pragma_options_field);
    found = true;
    if (multiple) {
      results.Add(options_value);
      continue;
    }
    if (options != nullptr) {
      *options = options_value.ptr();
    }
    return true;
  }

  if (found && options != nullptr) {
    *options = results.ptr();
  }
  return false;
}

bool Library::FindPragma(Thread* T,
                         bool only_core,
                         const Object& obj,
                         const String& pragma_name,
                         bool multiple,
                         Object* options) {
  auto Z = T->zone();
  auto& lib = Library::Handle(Z);

  if (obj.IsLibrary()) {
    lib = Library::Cast(obj).ptr();
  } else if (obj.IsClass()) {
    auto& klass = Class::Cast(obj);
    if (!klass.has_pragma()) return false;
    lib = klass.library();
  } else if (obj.IsFunction()) {
    auto& function = Function::Cast(obj);
    if (!function.has_pragma()) return false;
    lib = Class::Handle(Z, function.Owner()).library();
  } else if (obj.IsField()) {
    auto& field = Field::Cast(obj);
    if (!field.has_pragma()) return false;
    lib = Class::Handle(Z, field.Owner()).library();
  } else {
    UNREACHABLE();
  }

  if (only_core && !lib.IsAnyCoreLibrary()) {
    return false;
  }

  Object& metadata_obj = Object::Handle(Z, lib.GetMetadata(obj));
  if (metadata_obj.IsUnwindError()) {
    Report::LongJump(UnwindError::Cast(metadata_obj));
  }

  return FindPragmaInMetadata(T, metadata_obj, pragma_name, multiple, options);
}

bool Function::IsDynamicInvocationForwarderName(const String& name) {
  return IsDynamicInvocationForwarderName(name.ptr());
}

bool Function::IsDynamicInvocationForwarderName(StringPtr name) {
  return String::StartsWith(name, Symbols::DynamicPrefix().ptr());
}

StringPtr Function::DemangleDynamicInvocationForwarderName(const String& name) {
  if (name.ptr() == Symbols::DynamicImplicitCall().ptr()) {
    return Symbols::call().ptr();
  }
  const intptr_t kDynamicPrefixLength = 4;  // "dyn:"
  ASSERT(Symbols::DynamicPrefix().Length() == kDynamicPrefixLength);
  return Symbols::New(Thread::Current(), name, kDynamicPrefixLength,
                      name.Length() - kDynamicPrefixLength);
}

const String& Function::DropImplicitCallPrefix(const String& name) {
  if (name.ptr() == Symbols::DynamicImplicitCall().ptr()) {
    return Symbols::DynamicCall();
  }
  return name;
}

StringPtr Function::CreateDynamicInvocationForwarderName(const String& name) {
  return Symbols::FromConcat(Thread::Current(), Symbols::DynamicPrefix(), name);
}

#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES)
FunctionPtr Function::CreateDynamicInvocationForwarder(
    const String& mangled_name) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  Function& forwarder = Function::Handle(zone);
  // Load with relaxed atomics to prevent data race with updating original's
  // properties that are overridden below for the copy anyway.
  forwarder ^= Object::Clone(*this, Heap::kOld,
                             /*load_with_relaxed_atomics=*/true);

  forwarder.reset_unboxed_parameters_and_return();

  forwarder.set_name(mangled_name);
  forwarder.set_is_native(false);
  // TODO(dartbug.com/37737): Currently, we intentionally keep the recognized
  // kind when creating the dynamic invocation forwarder.
  forwarder.set_kind(UntaggedFunction::kDynamicInvocationForwarder);
  forwarder.set_modifier(UntaggedFunction::kNoModifier);
  forwarder.set_is_debuggable(false);

  // TODO(vegorov) for error reporting reasons it is better to make this
  // function visible and instead use a TailCall to invoke the target.
  // Our TailCall instruction is not ready for such usage though it
  // blocks inlining and can't take Function-s only Code objects.
  forwarder.set_is_visible(false);

#if defined(DART_DYNAMIC_MODULES)
  if (HasBytecode()) {
    forwarder.ClearBytecode();
  }
#endif
  forwarder.ClearICDataArray();
  forwarder.ClearCode();
  forwarder.set_usage_counter(0);
  forwarder.set_deoptimization_counter(0);
  forwarder.set_optimized_instruction_count(0);
  forwarder.set_inlining_depth(0);
  forwarder.set_optimized_call_site_count(0);

  forwarder.InheritKernelOffsetFrom(*this);
  forwarder.SetForwardingTarget(*this);

#if defined(DART_DYNAMIC_MODULES)
#if defined(DART_PRECOMPILED_RUNTIME)
  const bool attach_bytecode = true;
#else
  const bool attach_bytecode = is_declared_in_bytecode();
#endif
  if (attach_bytecode) {
    forwarder.AttachBytecode(Object::dynamic_invocation_forwarder_bytecode());
  }
#endif

  return forwarder.ptr();
}

FunctionPtr Function::GetDynamicInvocationForwarder(
    const String& mangled_name) const {
  ASSERT(IsDynamicInvocationForwarderName(mangled_name));
  ASSERT(mangled_name.ptr() != Symbols::DynamicImplicitCall().ptr());
  auto thread = Thread::Current();
  auto zone = thread->zone();
  const Class& owner = Class::Handle(zone, Owner());
  Function& result = Function::Handle(zone);

  // First we'll try to find it without using locks.
  result = owner.GetInvocationDispatcher(
      mangled_name, Array::null_array(),
      UntaggedFunction::kDynamicInvocationForwarder,
      /*create_if_absent=*/false);
  if (!result.IsNull()) return result.ptr();

  const bool needs_dyn_forwarder = NeedsDynamicInvocationForwarder();
  if (!needs_dyn_forwarder) {
    return ptr();
  }

  // If we failed to find it and possibly need to create it, use a write lock.
  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());

  // Try to find it again & return if it was added in the mean time.
  result = owner.GetInvocationDispatcher(
      mangled_name, Array::null_array(),
      UntaggedFunction::kDynamicInvocationForwarder,
      /*create_if_absent=*/false);
  if (!result.IsNull()) return result.ptr();

  // Otherwise create it & add it.
  result = CreateDynamicInvocationForwarder(mangled_name);
  owner.AddInvocationDispatcher(mangled_name, Array::null_array(), result);
  return result.ptr();
}

bool Function::NeedsDynamicInvocationForwarder() const {
  Zone* zone = Thread::Current()->zone();

  // Right now closures do not need a dyn:* forwarder.
  // See https://github.com/dart-lang/sdk/issues/40813
  if (IsClosureFunction()) return false;

  // Method extractors have no parameters to check and return value is a closure
  // and therefore not an unboxed primitive type.
  if (IsMethodExtractor()) {
    return false;
  }

  // Record field getters have no parameters to check and 'dynamic' return type.
  if (IsRecordFieldGetter()) {
    return false;
  }

  // Invoke field dispatchers are dynamically generated, will invoke a getter to
  // obtain the field value and then invoke ".call()" on the result.
  // Those dynamically generated dispathers don't have proper kernel metadata
  // associated with them - we can therefore not query if there are dynamic
  // calls to them or not and are therefore conservative.
  if (IsInvokeFieldDispatcher()) {
    return true;
  }

#if !defined(DART_PRECOMPILED_RUNTIME)
  // The dyn:* forwarders perform unboxing of parameters before calling the
  // actual target (which accepts unboxed parameters) and boxes return values
  // of the return value.
  if (HasUnboxedParameters() || HasUnboxedReturnValue()) {
    return true;
  }

  if (MaxNumberOfParametersInRegisters(zone) > 0) {
    return true;
  }
#endif

  // There are no parameters to type check for getters and if the return value
  // is boxed, then the dyn:* forwarder is not needed.
  if (IsImplicitGetterFunction()) {
    return false;
  }

  // Covariant parameters (both explicitly covariant and generic-covariant-impl)
  // are checked in the body of a function and therefore don't need checks in a
  // dynamic invocation forwarder. So dynamic invocation forwarder is only
  // needed if there are non-covariant parameters of non-top type.
  if (IsImplicitSetterFunction()) {
    const auto& field = Field::Handle(zone, accessor_field());
    return !(field.is_covariant() || field.is_generic_covariant_impl());
  }

  const auto& type_params = TypeParameters::Handle(zone, type_parameters());
  if (!type_params.IsNull()) {
    auto& bound = AbstractType::Handle(zone);
    for (intptr_t i = 0, n = type_params.Length(); i < n; ++i) {
      bound = type_params.BoundAt(i);
      if (!bound.IsTopTypeForSubtyping() &&
          !type_params.IsGenericCovariantImplAt(i)) {
        return true;
      }
    }
  }

  const intptr_t num_params = NumParameters();
  BitVector is_covariant(zone, num_params);
  BitVector is_generic_covariant_impl(zone, num_params);
  ReadParameterCovariance(&is_covariant, &is_generic_covariant_impl);

  auto& type = AbstractType::Handle(zone);
  for (intptr_t i = NumImplicitParameters(); i < num_params; ++i) {
    type = ParameterTypeAt(i);
    if (!type.IsTopTypeForSubtyping() &&
        !is_generic_covariant_impl.Contains(i) && !is_covariant.Contains(i)) {
      return true;
    }
  }

  return false;
}

void Function::ReadParameterCovariance(
    BitVector* is_covariant,
    BitVector* is_generic_covariant_impl) const {
#if defined(DART_DYNAMIC_MODULES)
  if (is_declared_in_bytecode()) {
    bytecode::BytecodeReader::ReadParameterCovariance(
        *this, is_covariant, is_generic_covariant_impl);
    return;
  }
#endif
#if !defined(DART_PRECOMPILED_RUNTIME)
  kernel::ReadParameterCovariance(*this, is_covariant,
                                  is_generic_covariant_impl);
#endif
}

#endif

bool AbstractType::InstantiateAndTestSubtype(
    AbstractType* subtype,
    AbstractType* supertype,
    const TypeArguments& instantiator_type_args,
    const TypeArguments& function_type_args) {
  if (!subtype->IsInstantiated()) {
    *subtype = subtype->InstantiateFrom(
        instantiator_type_args, function_type_args, kAllFree, Heap::kOld);
  }
  if (!supertype->IsInstantiated()) {
    *supertype = supertype->InstantiateFrom(
        instantiator_type_args, function_type_args, kAllFree, Heap::kOld);
  }
  return subtype->IsSubtypeOf(*supertype, Heap::kOld);
}

ArrayPtr Class::invocation_dispatcher_cache() const {
  return untag()->invocation_dispatcher_cache<std::memory_order_acquire>();
}

void Class::Finalize() const {
  auto thread = Thread::Current();
  auto isolate_group = thread->isolate_group();
  ASSERT(!thread->isolate_group()->all_classes_finalized());
  ASSERT(!is_finalized());
  // Prefinalized classes have a VM internal representation and no Dart fields.
  // Their instance size  is precomputed and field offsets are known.
  if (!is_prefinalized()) {
    // Compute offsets of instance fields, instance size and bitmap for unboxed
    // fields.
    const auto host_bitmap = CalculateFieldOffsets();
    if (ptr() == isolate_group->class_table()->At(id())) {
      if (!ClassTable::IsTopLevelCid(id())) {
        // Unless class is top-level, which don't get instantiated,
        // sets the new size in the class table.
        isolate_group->class_table()->UpdateClassSize(id(), ptr());
        isolate_group->class_table()->SetUnboxedFieldsMapAt(id(), host_bitmap);
      }
    }
  }

#if defined(DEBUG)
  if (is_const()) {
    // Double-check that all fields are final (CFE should guarantee that if it
    // marks the class as having a constant constructor).
    auto Z = thread->zone();
    const auto& super_class = Class::Handle(Z, SuperClass());
    ASSERT(super_class.IsNull() || super_class.is_const());
    const auto& fields = Array::Handle(Z, this->fields());
    auto& field = Field::Handle(Z);
    for (intptr_t i = 0; i < fields.Length(); ++i) {
      field ^= fields.At(i);
      ASSERT(field.is_static() || field.is_final());
    }
  }
#endif

  set_is_finalized();
}

#if defined(DEBUG)
static bool IsMutatorOrAtDeoptSafepoint() {
  Thread* thread = Thread::Current();
  return thread->IsDartMutatorThread() || thread->OwnsDeoptSafepoint();
}
#endif

#if !defined(DART_PRECOMPILED_RUNTIME)

class CHACodeArray : public WeakCodeReferences {
 public:
  explicit CHACodeArray(const Class& cls)
      : WeakCodeReferences(WeakArray::Handle(cls.dependent_code())),
        cls_(cls) {}

  virtual void UpdateArrayTo(const WeakArray& value) {
    // TODO(fschneider): Fails for classes in the VM isolate.
    cls_.set_dependent_code(value);
  }

  virtual void ReportDeoptimization(const Code& code) {
    if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
      Function& function = Function::Handle(code.function());
      THR_Print("Deoptimizing %s because CHA optimized (%s).\n",
                function.ToFullyQualifiedCString(), cls_.ToCString());
    }
  }

  virtual void ReportSwitchingCode(const Code& code) {
    if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
      Function& function = Function::Handle(code.function());
      THR_Print(
          "Switching %s to unoptimized code because CHA invalid"
          " (%s)\n",
          function.ToFullyQualifiedCString(), cls_.ToCString());
    }
  }

 private:
  const Class& cls_;
  DISALLOW_COPY_AND_ASSIGN(CHACodeArray);
};

void Class::RegisterCHACode(const Code& code) {
  if (FLAG_trace_cha) {
    THR_Print("RegisterCHACode '%s' depends on class '%s'\n",
              Function::Handle(code.function()).ToQualifiedCString(),
              ToCString());
  }
  DEBUG_ASSERT(IsMutatorOrAtDeoptSafepoint());
  ASSERT(code.is_optimized());
  CHACodeArray a(*this);
  a.Register(code);
}

void Class::DisableCHAOptimizedCode(const Class& subclass) {
  DEBUG_ASSERT(
      IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  CHACodeArray a(*this);
  if (FLAG_trace_deoptimization && a.HasCodes()) {
    if (subclass.IsNull()) {
      THR_Print("Deopt for CHA (all)\n");
    } else {
      THR_Print("Deopt for CHA (new subclass %s)\n", subclass.ToCString());
    }
  }
  a.DisableCode(/*are_mutators_stopped=*/false);
}

void Class::DisableAllCHAOptimizedCode() {
  DisableCHAOptimizedCode(Class::Handle());
}

WeakArrayPtr Class::dependent_code() const {
  DEBUG_ASSERT(
      IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
  return untag()->dependent_code();
}

void Class::set_dependent_code(const WeakArray& array) const {
  DEBUG_ASSERT(
      IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  untag()->set_dependent_code(array.ptr());
}

#endif  // !defined(DART_PRECOMPILED_RUNTIME)

bool Class::TraceAllocation(IsolateGroup* isolate_group) const {
#ifndef PRODUCT
  auto class_table = isolate_group->class_table();
  return class_table->ShouldTraceAllocationFor(id());
#else
  return false;
#endif
}

void Class::SetTraceAllocation(bool trace_allocation) const {
#ifndef PRODUCT
  auto isolate_group = IsolateGroup::Current();
  const bool changed = trace_allocation != this->TraceAllocation(isolate_group);
  if (changed) {
    auto class_table = isolate_group->class_table();
    class_table->SetTraceAllocationFor(id(), trace_allocation);
#ifdef TARGET_ARCH_IA32
    DisableAllocationStub();
#endif
  }
#else
  UNREACHABLE();
#endif
}

// Conventions:
// * For throwing a NSM in a library or top-level class (i.e., level is
//   kTopLevel), if a method was found but was incompatible, we pass the
//   signature of the found method as a string, otherwise the null instance.
// * Otherwise, for throwing a NSM in a class klass we use its runtime type as
//   receiver, i.e., klass.RareType().
static ObjectPtr ThrowNoSuchMethod(const Instance& receiver,
                                   const String& function_name,
                                   const Array& arguments,
                                   const Array& argument_names,
                                   const InvocationMirror::Level level,
                                   const InvocationMirror::Kind kind) {
  const Smi& invocation_type =
      Smi::Handle(Smi::New(InvocationMirror::EncodeType(level, kind)));

  ASSERT(!receiver.IsNull() || level == InvocationMirror::Level::kTopLevel);
  ASSERT(level != InvocationMirror::Level::kTopLevel || receiver.IsString());
  const Array& args = Array::Handle(Array::New(7));
  args.SetAt(0, receiver);
  args.SetAt(1, function_name);
  args.SetAt(2, invocation_type);
  args.SetAt(3, Object::smi_zero());  // Type arguments length.
  args.SetAt(4, Object::null_type_arguments());
  args.SetAt(5, arguments);
  args.SetAt(6, argument_names);

  const Library& libcore = Library::Handle(Library::CoreLibrary());
  const Class& cls =
      Class::Handle(libcore.LookupClass(Symbols::NoSuchMethodError()));
  ASSERT(!cls.IsNull());
  const auto& error = cls.EnsureIsFinalized(Thread::Current());
  ASSERT(error == Error::null());
  const Function& throwNew =
      Function::Handle(cls.LookupFunctionAllowPrivate(Symbols::ThrowNew()));
  return DartEntry::InvokeFunction(throwNew, args);
}

static ObjectPtr ThrowTypeError(const TokenPosition token_pos,
                                const Instance& src_value,
                                const AbstractType& dst_type,
                                const String& dst_name) {
  const Array& args = Array::Handle(Array::New(4));
  const Smi& pos = Smi::Handle(Smi::New(token_pos.Serialize()));
  args.SetAt(0, pos);
  args.SetAt(1, src_value);
  args.SetAt(2, dst_type);
  args.SetAt(3, dst_name);

  const Library& libcore = Library::Handle(Library::CoreLibrary());
  const Class& cls =
      Class::Handle(libcore.LookupClassAllowPrivate(Symbols::TypeError()));
  const auto& error = cls.EnsureIsFinalized(Thread::Current());
  ASSERT(error == Error::null());
  const Function& throwNew =
      Function::Handle(cls.LookupFunctionAllowPrivate(Symbols::ThrowNew()));
  return DartEntry::InvokeFunction(throwNew, args);
}

static bool WriteQualifiedMemberName(Zone* zone,
                                     BaseTextBuffer* buffer,
                                     const Object& member) {
  if (member.IsFunction()) {
    const auto& fun = Function::Cast(member);
    const auto& cls = Class::Handle(zone, fun.Owner());
    if (WriteQualifiedMemberName(zone, buffer, cls)) {
      buffer->AddString(".");
    }
    buffer->AddString(fun.UserVisibleNameCString());
    if (!fun.IsRegularFunction()) {
      buffer->Printf(" (kind %s)", Function::KindToCString(fun.kind()));
    }
  } else if (member.IsField()) {
    const auto& field = Field::Cast(member);
    const auto& cls = Class::Handle(field.Owner());
    if (WriteQualifiedMemberName(zone, buffer, cls)) {
      buffer->AddString(".");
    }
    const auto& name = String::Handle(field.name());
    buffer->AddString(name.ToCString());
  } else if (member.IsClass()) {
    const Class& cls = Class::Cast(member);
    const Library& lib = Library::Handle(cls.library());
    if (!lib.IsNull()) {
      const String& name = String::Handle(lib.url());
      buffer->Printf("%s::", name.ToCString());
    }
    if (!cls.IsTopLevel()) {
      buffer->AddString(cls.UserVisibleNameCString());
    }
    return !cls.IsTopLevel();
  }
  return false;
}

#if defined(DART_PRECOMPILED_RUNTIME)
DART_WARN_UNUSED_RESULT
static bool VerifyEntryPointHelper(const Object& object,
                                   EntryPointPragma expected) {
  // Annotations are discarded in the AOT snapshot, so we can't determine
  // precisely if this member was marked as an entry-point. Instead, we use
  // "has_pragma()" as a proxy, since that bit is usually retained.

  if (object.IsClass()) {
    return Class::Cast(object).has_pragma() &&
           expected == EntryPointPragma::kAlways;
  }
  if (object.IsField()) {
    return Field::Cast(object).has_pragma() &&
           expected != EntryPointPragma::kCallOnly;
  }
  if (!object.IsFunction()) {
    FATAL("Unexpected annotated node %s", object.ToCString());
  }

  const auto& f = Function::Cast(object);
  if (!f.has_pragma()) return false;

  // For non-closurization uses, if the function does not have code
  // attached, that means it was not properly annotated to allow the use.

  if (f.IsGetterFunction()) {
    return EntryPointPragmaUtils::AllowsGet(expected) && f.HasCode();
  }
  if (f.IsSetterFunction()) {
    return EntryPointPragmaUtils::AllowsSet(expected) && f.HasCode();
  }
  if (EntryPointPragmaUtils::AllowsCall(expected)) {
    return f.HasCode();
  }
  if (f.IsConstructor()) {
    // We're not checking for a call, which is the only allowed access.
    return false;
  }
  if (EntryPointPragmaUtils::AllowsGet(expected)) {
    // For non-getter functions, a 'get' entry point expectation denotes
    // closurization. The precompiler saves the implicit closure
    // function information if the function is properly annotated.
    return f.HasImplicitClosureFunction();
  }
  return false;
}
#endif

DART_WARN_UNUSED_RESULT
static ErrorPtr VerifyEntryPoint(const Library& lib,
                                 const Object& member,
                                 const Object& annotated,
                                 EntryPointPragma expected) {
  ASSERT(expected != EntryPointPragma::kNever);
  auto* const thread = Thread::Current();
  auto* const zone = thread->zone();
  // Special cases for certain types of functions that should delegate to
  // different members within the same class.
  if (member.IsFunction()) {
    const auto& fun = Function::Cast(member);
    if (fun.IsMethodExtractor()) {
      ASSERT(expected == EntryPointPragma::kGetterOnly);
      // To be able to call a method extractor, the original method needs to
      // be annotated for closure retrieval.
      const auto& closure =
          Function::Handle(zone, fun.extracted_method_closure());
      return VerifyEntryPoint(
          lib, closure, annotated.IsNull() ? annotated : closure, expected);
    } else if (fun.IsImplicitClosureFunction()) {
      // Check the annotations on the parent function instead.
      const auto& parent = Function::Handle(zone, fun.parent_function());
      return VerifyEntryPoint(
          lib, parent, annotated.IsNull() ? annotated : parent, expected);
    } else if (fun.IsImplicitGetterOrSetter()) {
      ASSERT(fun.IsImplicitSetterFunction() ||
             expected == EntryPointPragma::kGetterOnly);
      ASSERT(!fun.IsImplicitSetterFunction() ||
             expected == EntryPointPragma::kSetterOnly);
      // For implicit getters or setters, the field must be properly annotated.
      const auto& field = Field::Handle(zone, fun.accessor_field());
#if defined(DART_PRECOMPILED_RUNTIME)
      if (!fun.HasCode()) {
        return VerifyEntryPoint(lib, field, Object::null_object(), expected);
      }
#endif
      return VerifyEntryPoint(lib, field,
                              annotated.IsNull() ? annotated : field, expected);
    }
  }

  // For method and fields, the expected pragma should always be more specific.
  ASSERT_EQUAL(member.IsClass(), expected == EntryPointPragma::kAlways);

  // A null annotated object is used to signal an error should always be thrown.
  if (!annotated.IsNull()) {
    bool is_marked_entrypoint = false;
#if defined(DART_PRECOMPILED_RUNTIME)
    is_marked_entrypoint = VerifyEntryPointHelper(annotated, expected);
#else
    const auto& metadata = Object::Handle(zone, lib.GetMetadata(annotated));
    if (metadata.IsError()) {
      return Error::RawCast(metadata.ptr());
    }
    ASSERT(!metadata.IsNull() && metadata.IsArray());
    const EntryPointPragma pragma =
        FindEntryPointPragma(thread->isolate_group(), Array::Cast(metadata),
                             &Field::Handle(zone), &Object::Handle(zone));
    ASSERT(pragma != EntryPointPragma::kCallOnly || annotated.IsFunction());
    is_marked_entrypoint =
        pragma == EntryPointPragma::kAlways || pragma == expected;
#endif
    if (is_marked_entrypoint) {
      return Error::null();
    }
  }

  ZoneTextBuffer buffer(zone);
  switch (expected) {
    case EntryPointPragma::kAlways:
      buffer.AddString("ERROR: To access '");
      WriteQualifiedMemberName(zone, &buffer, member);
      buffer.AddString("' from native code, it must be annotated.\n");
      break;
    case EntryPointPragma::kCallOnly:
      ASSERT(member.IsFunction());
      buffer.AddString("ERROR: To invoke '");
      WriteQualifiedMemberName(zone, &buffer, member);
      buffer.AddString("' from native code, it must be annotated.\n");
      break;
    case EntryPointPragma::kGetterOnly:
      if (member.IsField() ||
          (member.IsFunction() && Function::Cast(member).IsGetterFunction())) {
        buffer.AddString("ERROR: To retrieve the value of '");
        WriteQualifiedMemberName(zone, &buffer, member);
        buffer.AddString("' from native code, it must be annotated.\n");
      } else {
        const auto& function = Function::Cast(member);
        // Other types of functions cannot be closurized.
        if (!function.IsRegularFunction()) {
          // Other types of functions reaching here are internal errors.
          buffer.AddString("Cannot get closure value for method '");
          WriteQualifiedMemberName(zone, &buffer, function);
          buffer.Printf("' of kind %s",
                        Function::KindToCString(function.kind()));
          FATAL("%s", buffer.buffer());
        }
        buffer.AddString("ERROR: To closurize '");
        WriteQualifiedMemberName(zone, &buffer, function);
        buffer.AddString("' from native code, it must be annotated.\n");
      }
      break;
    case EntryPointPragma::kSetterOnly:
      if (member.IsField() ||
          (member.IsFunction() && Function::Cast(member).IsSetterFunction())) {
        buffer.AddString("ERROR: To set the value of '");
        WriteQualifiedMemberName(zone, &buffer, member);
        buffer.AddString("' from native code, it must be annotated.\n");
      } else {
        // Other types of functions reaching here are internal errors.
        buffer.AddString("Cannot set value of '");
        WriteQualifiedMemberName(zone, &buffer, member);
        buffer.AddString("'");
        FATAL("%s", buffer.buffer());
      }
      break;
    default:
      FATAL("Unexpected EntryPointPragma value %" Pd,
            static_cast<intptr_t>(expected));
  }
  buffer.AddString(
      "ERROR: See https://github.com/dart-lang/sdk/blob/master/runtime/"
      "docs/compiler/aot/entry_point_pragma.md\n");
  OS::PrintErr("%s", buffer.buffer());
  return ApiError::New(String::Handle(String::New(buffer.buffer())));
}

#if defined(DART_PRECOMPILED_RUNTIME)
DART_WARN_UNUSED_RESULT
static ErrorPtr EntryPointFunctionInvocationError(const Function& function) {
  // Ensures a failure by passing null for the annotated object.
  return VerifyEntryPoint(Library::Handle(Library::null()), function,
                          Object::null_object(), EntryPointPragma::kCallOnly);
}
#endif

ObjectPtr Class::InvokeGetter(const String& getter_name,
                              bool check_is_entrypoint,
                              bool respect_reflectable,
                              bool for_invocation) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  CHECK_ERROR(EnsureIsFinalized(thread));

  // Note static fields do not have implicit getters.
  const Field& field = Field::Handle(zone, LookupStaticField(getter_name));

  if (field.IsNull() || field.IsUninitialized()) {
    const String& internal_getter_name =
        String::Handle(zone, Field::GetterName(getter_name));
    Function& getter =
        Function::Handle(zone, LookupStaticFunction(internal_getter_name));

    if (getter.IsNull() || (respect_reflectable && !getter.is_reflectable())) {
      if (for_invocation) {
        // LookupStaticFunction(getter_name) has already failed in Invoke().
        // Instead of throwing an NSM, indicate that no getter was found
        // by returning a value that cannot be returned by a getter (here,
        // the sentinel value).
        return Object::sentinel().ptr();
      } else if (getter.IsNull()) {
        getter = LookupStaticFunction(getter_name);
        if (!getter.IsNull()) {
          if (getter.SafeToClosurize()) {
            if (check_is_entrypoint) {
              CHECK_ERROR(
                  getter.VerifyEntryPoint(EntryPointPragma::kGetterOnly));
            }
            // Looking for a getter but found a regular method: closurize it.
            const Function& closure_function =
                Function::Handle(zone, getter.ImplicitClosureFunction());
            return closure_function.ImplicitStaticClosure();
          }
        }
      }

      return ThrowNoSuchMethod(AbstractType::Handle(zone, RareType()),
                               getter_name, Object::null_array(),
                               Object::null_array(), InvocationMirror::kStatic,
                               InvocationMirror::kGetter);
    }

    if (check_is_entrypoint) {
      CHECK_ERROR(getter.VerifyEntryPoint(EntryPointPragma::kGetterOnly));
    }

    // Invoke the getter and return the result.
    return DartEntry::InvokeFunction(getter, Object::empty_array());
  }

  if (check_is_entrypoint) {
    CHECK_ERROR(field.VerifyEntryPoint(EntryPointPragma::kGetterOnly));
  }

  return field.StaticValue();
}

ObjectPtr Class::InvokeSetter(const String& setter_name,
                              const Instance& value,
                              bool check_is_entrypoint,
                              bool respect_reflectable) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  CHECK_ERROR(EnsureIsFinalized(thread));

  // Check for real fields and user-defined setters.
  const Field& field = Field::Handle(zone, LookupStaticField(setter_name));
  const String& internal_setter_name =
      String::Handle(zone, Field::SetterName(setter_name));

  if (field.IsNull()) {
    const Function& setter =
        Function::Handle(zone, LookupStaticFunction(internal_setter_name));
    const int kNumArgs = 1;
    const Array& args = Array::Handle(zone, Array::New(kNumArgs));
    args.SetAt(0, value);
    if (setter.IsNull() || (respect_reflectable && !setter.is_reflectable())) {
      return ThrowNoSuchMethod(AbstractType::Handle(zone, RareType()),
                               internal_setter_name, args, Object::null_array(),
                               InvocationMirror::kStatic,
                               InvocationMirror::kSetter);
    }
    const auto& type = AbstractType::Handle(zone, setter.ParameterTypeAt(0));
    if (!value.RuntimeTypeIsSubtypeOf(type, Object::null_type_arguments(),
                                      Object::null_type_arguments())) {
      const String& argument_name =
          String::Handle(zone, setter.ParameterNameAt(0));
      return ThrowTypeError(setter.token_pos(), value, type, argument_name);
    }
    if (check_is_entrypoint) {
      CHECK_ERROR(setter.VerifyEntryPoint(EntryPointPragma::kSetterOnly));
    }
    // Invoke the setter and return the result.
    return DartEntry::InvokeFunction(setter, args);
  }

  if (field.is_final() || (respect_reflectable && !field.is_reflectable())) {
    const int kNumArgs = 1;
    const Array& args = Array::Handle(zone, Array::New(kNumArgs));
    args.SetAt(0, value);
    return ThrowNoSuchMethod(AbstractType::Handle(zone, RareType()),
                             internal_setter_name, args, Object::null_array(),
                             InvocationMirror::kStatic,
                             InvocationMirror::kSetter);
  }

  const auto& type = AbstractType::Handle(zone, field.type());
  if (!value.RuntimeTypeIsSubtypeOf(type, Object::null_type_arguments(),
                                    Object::null_type_arguments())) {
    const String& argument_name = String::Handle(zone, field.name());
    return ThrowTypeError(field.token_pos(), value, type, argument_name);
  }
  if (check_is_entrypoint) {
    CHECK_ERROR(field.VerifyEntryPoint(EntryPointPragma::kSetterOnly));
  }
  field.SetStaticValue(value);
  return value.ptr();
}

// Creates a new array of boxed arguments suitable for invoking the callable
// from the original boxed arguments for a static call. Also sets the contents
// of the handle pointed to by [callable_args_desc_array_out] to an appropriate
// arguments descriptor array for the new arguments.
//
// Assumes [arg_names] are consistent with [static_args_descriptor].
static ArrayPtr CreateCallableArgumentsFromStatic(
    Zone* zone,
    const Instance& receiver,
    const Array& static_args,
    const Array& arg_names,
    const ArgumentsDescriptor& static_args_descriptor) {
  const intptr_t num_static_type_args = static_args_descriptor.TypeArgsLen();
  const intptr_t num_static_args = static_args_descriptor.Count();
  // Double check that the static args descriptor expects boxed arguments
  // and the static args descriptor is consistent with the static arguments.
  ASSERT_EQUAL(static_args_descriptor.Size(), num_static_args);
  ASSERT_EQUAL(static_args.Length(),
               num_static_args + (num_static_type_args > 0 ? 1 : 0));
  // Add an additional slot to store the callable as the receiver.
  const auto& callable_args =
      Array::Handle(zone, Array::New(static_args.Length() + 1));
  const intptr_t first_arg_index = static_args_descriptor.FirstArgIndex();
  auto& temp = Object::Handle(zone);
  // Copy the static args into the corresponding slots of the callable args.
  if (num_static_type_args > 0) {
    temp = static_args.At(0);
    callable_args.SetAt(0, temp);
  }
  for (intptr_t i = first_arg_index; i < static_args.Length(); i++) {
    temp = static_args.At(i);
    callable_args.SetAt(i + 1, temp);
  }
  // Set the receiver slot in the callable args.
  callable_args.SetAt(first_arg_index, receiver);
  return callable_args.ptr();
}

ObjectPtr Class::Invoke(const String& function_name,
                        const Array& args,
                        const Array& arg_names,
                        bool check_is_entrypoint,
                        bool respect_reflectable) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  CHECK_ERROR(EnsureIsFinalized(thread));

  // We don't pass any explicit type arguments, which will be understood as
  // using dynamic for any function type arguments by lower layers.
  const int kTypeArgsLen = 0;
  const Array& args_descriptor_array = Array::Handle(
      zone, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length(),
                                          arg_names, Heap::kNew));
  ArgumentsDescriptor args_descriptor(args_descriptor_array);

  Function& function =
      Function::Handle(zone, LookupStaticFunction(function_name));

  if (function.IsNull()) {
    // Didn't find a method: try to find a getter and invoke call on its result.
    const Object& getter_result =
        Object::Handle(zone, InvokeGetter(function_name, check_is_entrypoint,
                                          respect_reflectable,
                                          /*for_invocation=*/true));
    if (getter_result.IsError()) {
      return getter_result.ptr();
    } else if (getter_result.ptr() != Object::sentinel().ptr()) {
      const auto& call_args_descriptor_array = Array::Handle(
          zone, ArgumentsDescriptor::NewBoxed(args_descriptor.TypeArgsLen(),
                                              args_descriptor.Count() + 1,
                                              arg_names, Heap::kNew));
      const auto& call_args = Array::Handle(
          zone,
          CreateCallableArgumentsFromStatic(zone, Instance::Cast(getter_result),
                                            args, arg_names, args_descriptor));
      return DartEntry::InvokeClosure(thread, call_args,
                                      call_args_descriptor_array);
    }
  }

  if (function.IsNull() ||
      !function.AreValidArguments(args_descriptor, nullptr) ||
      (respect_reflectable && !function.is_reflectable())) {
    return ThrowNoSuchMethod(
        AbstractType::Handle(zone, RareType()), function_name, args, arg_names,
        InvocationMirror::kStatic, InvocationMirror::kMethod);
  }
  // This is a static function, so we pass an empty instantiator tav.
  ASSERT(function.is_static());
  ObjectPtr type_error = function.DoArgumentTypesMatch(
      args, args_descriptor, Object::empty_type_arguments());
  if (type_error != Error::null()) {
    return type_error;
  }
  if (check_is_entrypoint) {
    CHECK_ERROR(function.VerifyEntryPoint(EntryPointPragma::kCallOnly));
  }
  return DartEntry::InvokeFunction(function, args, args_descriptor_array);
}

#if !defined(DART_PRECOMPILED_RUNTIME)

static ObjectPtr LoadExpressionEvaluationFunction(
    Zone* zone,
    const ExternalTypedData& kernel_buffer,
    const String& library_url,
    const String& klass) {
  std::unique_ptr<kernel::Program> kernel_pgm =
      kernel::Program::ReadFromTypedData(kernel_buffer);

  if (kernel_pgm == nullptr) {
    return ApiError::New(String::Handle(
        zone, String::New("Kernel isolate returned ill-formed kernel.")));
  }

  auto& result = Object::Handle(zone);
  {
    kernel::KernelLoader loader(kernel_pgm.get(),
                                /*uri_to_source_table=*/nullptr);
    result = loader.LoadExpressionEvaluationFunction(library_url, klass);
    kernel_pgm.reset();
  }
  if (result.IsError()) return result.ptr();
  return Function::Cast(result).ptr();
}

static bool EvaluationFunctionNeedsReceiver(Thread* thread,
                                            Zone* zone,
                                            const Function& eval_function) {
  auto parsed_function = new ParsedFunction(
      thread, Function::ZoneHandle(zone, eval_function.ptr()));
  parsed_function->EnsureKernelScopes();
  return parsed_function->is_receiver_used();
}

static ObjectPtr EvaluateCompiledExpressionHelper(
    Zone* zone,
    const Function& eval_function,
    const Array& type_definitions,
    const Array& arguments,
    const TypeArguments& type_arguments) {
  // type_arguments is null if all type arguments are dynamic.
  if (type_definitions.Length() == 0 || type_arguments.IsNull()) {
    return DartEntry::InvokeFunction(eval_function, arguments);
  }

  intptr_t num_type_args = type_arguments.Length();
  const auto& real_arguments =
      Array::Handle(zone, Array::New(arguments.Length() + 1));
  real_arguments.SetAt(0, type_arguments);
  Object& arg = Object::Handle(zone);
  for (intptr_t i = 0; i < arguments.Length(); ++i) {
    arg = arguments.At(i);
    real_arguments.SetAt(i + 1, arg);
  }

  const Array& args_desc =
      Array::Handle(zone, ArgumentsDescriptor::NewBoxed(
                              num_type_args, arguments.Length(), Heap::kNew));
  return DartEntry::InvokeFunction(eval_function, real_arguments, args_desc);
}

#endif  // !defined(DART_PRECOMPILED_RUNTIME)

ObjectPtr Library::EvaluateCompiledExpression(
    const ExternalTypedData& kernel_buffer,
    const Array& type_definitions,
    const Array& arguments,
    const TypeArguments& type_arguments) const {
  const auto& klass = Class::Handle(toplevel_class());
  return klass.EvaluateCompiledExpression(kernel_buffer, type_definitions,
                                          arguments, type_arguments);
}

ObjectPtr Class::EvaluateCompiledExpression(
    const ExternalTypedData& kernel_buffer,
    const Array& type_definitions,
    const Array& arguments,
    const TypeArguments& type_arguments) const {
  auto thread = Thread::Current();
  const auto& library = Library::Handle(thread->zone(), this->library());
  return Instance::EvaluateCompiledExpression(
      thread, Instance::null_object(), library, *this, kernel_buffer,
      type_definitions, arguments, type_arguments);
}

ObjectPtr Instance::EvaluateCompiledExpression(
    const Class& klass,
    const ExternalTypedData& kernel_buffer,
    const Array& type_definitions,
    const Array& arguments,
    const TypeArguments& type_arguments) const {
  auto thread = Thread::Current();
  auto zone = thread->zone();
  const auto& library = Library::Handle(zone, klass.library());
  return Instance::EvaluateCompiledExpression(thread, *this, library, klass,
                                              kernel_buffer, type_definitions,
                                              arguments, type_arguments);
}

ObjectPtr Instance::EvaluateCompiledExpression(
    Thread* thread,
    const Object& receiver,
    const Library& library,
    const Class& klass,
    const ExternalTypedData& kernel_buffer,
    const Array& type_definitions,
    const Array& arguments,
    const TypeArguments& type_arguments) {
  auto zone = Thread::Current()->zone();
#if defined(DART_PRECOMPILED_RUNTIME)
  const auto& error_str = String::Handle(
      zone,
      String::New("Expression evaluation not available in precompiled mode."));
  return ApiError::New(error_str);
#else
  if (IsInternalOnlyClassId(klass.id()) || (klass.id() == kTypeArgumentsCid)) {
    const auto& exception = Instance::Handle(
        zone, String::New("Expressions can be evaluated only with regular Dart "
                          "instances/classes."));
    return UnhandledException::New(exception, StackTrace::null_instance());
  }

  const auto& url = String::Handle(zone, library.url());
  const auto& klass_name = klass.IsTopLevel()
                               ? String::null_string()
                               : String::Handle(zone, klass.UserVisibleName());

  const auto& result = Object::Handle(
      zone,
      LoadExpressionEvaluationFunction(zone, kernel_buffer, url, klass_name));
  if (result.IsError()) return result.ptr();

  const auto& eval_function = Function::Cast(result);

#if defined(DEBUG)
  for (intptr_t i = 0; i < arguments.Length(); ++i) {
    ASSERT(arguments.At(i) != Object::optimized_out().ptr());
    ASSERT(arguments.At(i) != Object::sentinel().ptr());
  }
#endif  // defined(DEBUG)

  auto& all_arguments = Array::Handle(zone, arguments.ptr());
  if (!eval_function.is_static()) {
    // `this` may be optimized out (e.g. not accessible from breakpoint due to
    // not being captured by closure). We allow this as long as the evaluation
    // function doesn't actually need `this`.
    if (receiver.IsNull() || receiver.ptr() == Object::optimized_out().ptr()) {
      if (EvaluationFunctionNeedsReceiver(thread, zone, eval_function)) {
        return Object::optimized_out().ptr();
      }
    }

    all_arguments = Array::New(1 + arguments.Length());
    auto& param = PassiveObject::Handle();
    all_arguments.SetAt(0, receiver);
    for (intptr_t i = 0; i < arguments.Length(); i++) {
      param = arguments.At(i);
      all_arguments.SetAt(i + 1, param);
    }
  }

  return EvaluateCompiledExpressionHelper(zone, eval_function, type_definitions,
                                          all_arguments, type_arguments);
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
}

void Class::EnsureDeclarationLoaded() const {
  if (!is_declaration_loaded()) {
#if defined(DART_DYNAMIC_MODULES)
    // Loading of class declaration can be postponed until needed
    // if class comes from bytecode.
    if (is_declared_in_bytecode()) {
      Thread* thread = Thread::Current();
      SafepointWriteRwLocker ml(thread,
                                thread->isolate_group()->program_lock());
      if (is_declaration_loaded()) {
        return;
      }
      bytecode::BytecodeReader::LoadClassDeclaration(*this);
      ASSERT(is_declaration_loaded());
      ASSERT(is_type_finalized());
      return;
    }
#endif  // defined(DART_DYNAMIC_MODULES)
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
#else
    FATAL("Unable to use class %s which is not loaded yet.", ToCString());
#endif  // defined(DART_PRECOMPILED_RUNTIME)
  }
}

// Ensure that top level parsing of the class has been done.
ErrorPtr Class::EnsureIsFinalized(Thread* thread) const {
  ASSERT(!IsNull());
  if (is_finalized()) {
    return Error::null();
  }
#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES)
  UNREACHABLE();
  return Error::null();
#else
  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
  if (is_finalized()) {
    return Error::null();
  }
  LeaveCompilerScope ncs(thread);
  ASSERT(thread != nullptr);
  const Error& error =
      Error::Handle(thread->zone(), ClassFinalizer::LoadClassMembers(*this));
  if (!error.IsNull()) {
    ASSERT(thread == Thread::Current());
    if (thread->long_jump_base() != nullptr) {
      Report::LongJump(error);
      UNREACHABLE();
    }
  }
  return error.ptr();
#endif  // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES)
}

// Ensure that code outdated by finalized class is cleaned up, new instance of
// this class is ready to be allocated.
ErrorPtr Class::EnsureIsAllocateFinalized(Thread* thread) const {
  ASSERT(!IsNull());
  if (is_allocate_finalized()) {
    return Error::null();
  }
  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
  if (is_allocate_finalized()) {
    return Error::null();
  }
  ASSERT(thread != nullptr);
  Error& error = Error::Handle(thread->zone(), EnsureIsFinalized(thread));
  if (!error.IsNull()) {
    ASSERT(thread == Thread::Current());
    if (thread->long_jump_base() != nullptr) {
      Report::LongJump(error);
      UNREACHABLE();
    }
  }
  // May be allocate-finalized recursively during EnsureIsFinalized.
  if (is_allocate_finalized()) {
    return Error::null();
  }
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  error ^= ClassFinalizer::AllocateFinalizeClass(*this);
#endif  // defined(DART_PRECOMPILED_RUNTIME)
  return error.ptr();
}

void Class::SetFields(const Array& value) const {
  ASSERT(!value.IsNull());
#if defined(DEBUG)
  Thread* thread = Thread::Current();
  ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
  // Verify that all the fields in the array have this class as owner.
  Field& field = Field::Handle();
  intptr_t len = value.Length();
  for (intptr_t i = 0; i < len; i++) {
    field ^= value.At(i);
    ASSERT(field.IsOriginal());
    ASSERT(field.Owner() == ptr());
  }
#endif
  // The value of static fields is already initialized to null.
  set_fields(value);
}

void Class::AddField(const Field& field) const {
#if defined(DEBUG)
  Thread* thread = Thread::Current();
  ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
#endif
  const Array& arr = Array::Handle(fields());
  const Array& new_arr = Array::Handle(Array::Grow(arr, arr.Length() + 1));
  new_arr.SetAt(arr.Length(), field);
  SetFields(new_arr);
}

void Class::AddFields(const GrowableArray<const Field*>& new_fields) const {
#if defined(DEBUG)
  Thread* thread = Thread::Current();
  ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
#endif
  const intptr_t num_new_fields = new_fields.length();
  if (num_new_fields == 0) return;
  const Array& arr = Array::Handle(fields());
  const intptr_t num_old_fields = arr.Length();
  const Array& new_arr = Array::Handle(
      Array::Grow(arr, num_old_fields + num_new_fields, Heap::kOld));
  for (intptr_t i = 0; i < num_new_fields; i++) {
    new_arr.SetAt(i + num_old_fields, *new_fields.At(i));
  }
  SetFields(new_arr);
}

intptr_t Class::FindFieldIndex(const Field& needle) const {
  Thread* thread = Thread::Current();
  if (EnsureIsFinalized(thread) != Error::null()) {
    return -1;
  }
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_FIELD_HANDLESCOPE(thread);
  Array& fields = thread->ArrayHandle();
  Field& field = thread->FieldHandle();
  fields = this->fields();
  ASSERT(!fields.IsNull());
  for (intptr_t i = 0, n = fields.Length(); i < n; ++i) {
    field ^= fields.At(i);
    if (needle.ptr() == field.ptr()) {
      return i;
    }
  }
  // Not found.
  return -1;
}

FieldPtr Class::FieldFromIndex(intptr_t idx) const {
  Array& fields = Array::Handle(this->fields());
  if ((idx < 0) || (idx >= fields.Length())) {
    return Field::null();
  }
  return Field::RawCast(fields.At(idx));
}

bool Class::InjectCIDFields() const {
  if (library() != Library::InternalLibrary() ||
      Name() != Symbols::ClassID().ptr()) {
    return false;
  }

  auto thread = Thread::Current();
  auto isolate_group = thread->isolate_group();
  auto zone = thread->zone();
  Field& field = Field::Handle(zone);
  Smi& value = Smi::Handle(zone);
  String& field_name = String::Handle(zone);

  // clang-format off
  static const struct {
    const char* const field_name;
    const intptr_t cid;
  } cid_fields[] = {
#define CLASS_LIST_WITH_NULL(V)                                                \
    V(Null)                                                                    \
    CLASS_LIST_NO_OBJECT(V)
#define ADD_SET_FIELD(clazz)                                                   \
    {"cid" #clazz, k##clazz##Cid},
    CLASS_LIST_WITH_NULL(ADD_SET_FIELD)
#undef ADD_SET_FIELD
#undef CLASS_LIST_WITH_NULL
#define ADD_SET_FIELD(clazz)                                                   \
    {"cid" #clazz, kTypedData##clazz##Cid},                                    \
    {"cid" #clazz "View", kTypedData##clazz##ViewCid},                         \
    {"cidExternal" #clazz, kExternalTypedData##clazz##Cid},                    \
    {"cidUnmodifiable" #clazz "View", kUnmodifiableTypedData##clazz##ViewCid}, \
    CLASS_LIST_TYPED_DATA(ADD_SET_FIELD)
#undef ADD_SET_FIELD
    // Used in const hashing to determine whether we're dealing with a
    // user-defined const. See lib/_internal/vm/lib/compact_hash.dart.
    {"numPredefinedCids", kNumPredefinedCids},
  };
  // clang-format on

  const AbstractType& field_type = Type::Handle(zone, Type::IntType());
  for (size_t i = 0; i < ARRAY_SIZE(cid_fields); i++) {
    field_name = Symbols::New(thread, cid_fields[i].field_name);
    field = Field::New(field_name, /* is_static = */ true,
                       /* is_final = */ false,
                       /* is_const = */ true,
                       /* is_reflectable = */ false,
                       /* is_late = */ false, *this, field_type,
                       TokenPosition::kMinSource, TokenPosition::kMinSource);
    value = Smi::New(cid_fields[i].cid);
    isolate_group->RegisterStaticField(field, value);
    AddField(field);
  }

  return true;
}

template <class FakeInstance, class TargetFakeInstance>
ClassPtr Class::NewCommon(intptr_t index) {
  ASSERT(Object::class_class() != Class::null());
  const auto& result = Class::Handle(Object::Allocate<Class>(Heap::kOld));
  // Here kIllegalCid means not-yet-assigned.
  Object::VerifyBuiltinVtable<FakeInstance>(index == kIllegalCid ? kInstanceCid
                                                                 : index);
  NOT_IN_PRECOMPILED(result.set_token_pos(TokenPosition::kNoSource));
  NOT_IN_PRECOMPILED(result.set_end_token_pos(TokenPosition::kNoSource));
  const intptr_t host_instance_size = FakeInstance::InstanceSize();
  const intptr_t target_instance_size = compiler::target::RoundedAllocationSize(
      TargetFakeInstance::InstanceSize());
  result.set_instance_size(host_instance_size, target_instance_size);
  result.set_type_arguments_field_offset_in_words(kNoTypeArguments,
                                                  RTN::Class::kNoTypeArguments);
  const intptr_t host_next_field_offset = FakeInstance::NextFieldOffset();
  const intptr_t target_next_field_offset =
      TargetFakeInstance::NextFieldOffset();
  result.set_next_field_offset(host_next_field_offset,
                               target_next_field_offset);
  result.set_id(index);
  NOT_IN_PRECOMPILED(result.set_implementor_cid(kIllegalCid));
  result.set_num_type_arguments_unsafe(kUnknownNumTypeArguments);
  result.set_num_native_fields(0);
  result.set_state_bits(0);
  NOT_IN_PRECOMPILED(result.set_kernel_offset(0));
  result.InitEmptyFields();
  return result.ptr();
}

template <class FakeInstance, class TargetFakeInstance>
ClassPtr Class::New(intptr_t index,
                    IsolateGroup* isolate_group,
                    bool register_class,
                    bool is_abstract) {
  Class& result =
      Class::Handle(NewCommon<FakeInstance, TargetFakeInstance>(index));
  if (is_abstract) {
    result.set_is_abstract();
  }
  if (register_class) {
    isolate_group->class_table()->Register(result);
  }
  return result.ptr();
}

ClassPtr Class::New(const Library& lib,
                    const String& name,
                    const Script& script,
                    TokenPosition token_pos,
                    bool register_class) {
  Class& result =
      Class::Handle(NewCommon<Instance, RTN::Instance>(kIllegalCid));
  result.set_library(lib);
  result.set_name(name);
  result.set_script(script);
  NOT_IN_PRECOMPILED(result.set_token_pos(token_pos));

  // The size gets initialized to 0. Once the class gets finalized the class
  // finalizer will set the correct size.
  ASSERT(!result.is_finalized() && !result.is_prefinalized());
  result.set_instance_size_in_words(0, 0);

  if (register_class) {
    IsolateGroup::Current()->RegisterClass(result);
  }
  return result.ptr();
}

ClassPtr Class::NewInstanceClass() {
  return Class::New<Instance, RTN::Instance>(kIllegalCid,
                                             IsolateGroup::Current());
}

ClassPtr Class::NewNativeWrapper(const Library& library,
                                 const String& name,
                                 int field_count) {
  Class& cls = Class::Handle(library.LookupClass(name));
  if (cls.IsNull()) {
    cls = New(library, name, Script::Handle(), TokenPosition::kNoSource);
    cls.SetFields(Object::empty_array());
    cls.SetFunctions(Object::empty_array());
    // Set super class to Object.
    cls.set_super_type(Type::Handle(Type::ObjectType()));
    // Compute instance size. First word contains a pointer to a properly
    // sized typed array once the first native field has been set.
    const intptr_t host_instance_size =
        sizeof(UntaggedInstance) + kCompressedWordSize;
#if defined(DART_PRECOMPILER)
    const intptr_t target_instance_size =
        compiler::target::Instance::InstanceSize() +
        compiler::target::kCompressedWordSize;
#else
    const intptr_t target_instance_size =
        sizeof(UntaggedInstance) + compiler::target::kCompressedWordSize;
#endif
    cls.set_instance_size(
        RoundedAllocationSize(host_instance_size),
        compiler::target::RoundedAllocationSize(target_instance_size));
    cls.set_next_field_offset(host_instance_size, target_instance_size);
    cls.set_num_native_fields(field_count);
    cls.set_is_allocate_finalized();
    // The signature of the constructor yet to be added to this class will have
    // to be finalized explicitly, since the class is prematurely marked as
    // 'is_allocate_finalized' and finalization of member types will not occur.
    cls.set_is_declaration_loaded();
    cls.set_is_type_finalized();
    cls.set_is_synthesized_class();
    cls.set_is_isolate_unsendable(true);
    cls.set_is_deeply_immutable(true);
    NOT_IN_PRECOMPILED(cls.set_implementor_cid(kDynamicCid));
    library.AddClass(cls);
    return cls.ptr();
  } else {
    return Class::null();
  }
}

ClassPtr Class::NewStringClass(intptr_t class_id, IsolateGroup* isolate_group) {
  intptr_t host_instance_size, target_instance_size;
  if (class_id == kOneByteStringCid) {
    host_instance_size = OneByteString::InstanceSize();
    target_instance_size = compiler::target::RoundedAllocationSize(
        RTN::OneByteString::InstanceSize());
  } else {
    ASSERT(class_id == kTwoByteStringCid);
    host_instance_size = TwoByteString::InstanceSize();
    target_instance_size = compiler::target::RoundedAllocationSize(
        RTN::TwoByteString::InstanceSize());
  }
  Class& result = Class::Handle(New<String, RTN::String>(
      class_id, isolate_group, /*register_class=*/false));
  result.set_instance_size(host_instance_size, target_instance_size);

  const intptr_t host_next_field_offset = String::NextFieldOffset();
  const intptr_t target_next_field_offset = RTN::String::NextFieldOffset();
  result.set_next_field_offset(host_next_field_offset,
                               target_next_field_offset);
  result.set_is_prefinalized();
  ASSERT(IsDeeplyImmutableCid(class_id));
  result.set_is_deeply_immutable(true);
  isolate_group->class_table()->Register(result);
  return result.ptr();
}

ClassPtr Class::NewTypedDataClass(intptr_t class_id,
                                  IsolateGroup* isolate_group) {
  ASSERT(IsTypedDataClassId(class_id));
  const intptr_t host_instance_size = TypedData::InstanceSize();
  const intptr_t target_instance_size =
      compiler::target::RoundedAllocationSize(RTN::TypedData::InstanceSize());
  Class& result = Class::Handle(New<TypedData, RTN::TypedData>(
      class_id, isolate_group, /*register_class=*/false));
  result.set_instance_size(host_instance_size, target_instance_size);

  const intptr_t host_next_field_offset = TypedData::NextFieldOffset();
  const intptr_t target_next_field_offset = RTN::TypedData::NextFieldOffset();
  result.set_next_field_offset(host_next_field_offset,
                               target_next_field_offset);
  result.set_is_prefinalized();
  isolate_group->class_table()->Register(result);
  return result.ptr();
}

ClassPtr Class::NewTypedDataViewClass(intptr_t class_id,
                                      IsolateGroup* isolate_group) {
  ASSERT(IsTypedDataViewClassId(class_id));
  const intptr_t host_instance_size = TypedDataView::InstanceSize();
  const intptr_t target_instance_size = compiler::target::RoundedAllocationSize(
      RTN::TypedDataView::InstanceSize());
  Class& result = Class::Handle(New<TypedDataView, RTN::TypedDataView>(
      class_id, isolate_group, /*register_class=*/false));
  result.set_instance_size(host_instance_size, target_instance_size);

  const intptr_t host_next_field_offset = TypedDataView::NextFieldOffset();
  const intptr_t target_next_field_offset =
      RTN::TypedDataView::NextFieldOffset();
  result.set_next_field_offset(host_next_field_offset,
                               target_next_field_offset);
  result.set_is_prefinalized();
  isolate_group->class_table()->Register(result);
  return result.ptr();
}

ClassPtr Class::NewUnmodifiableTypedDataViewClass(intptr_t class_id,
                                                  IsolateGroup* isolate_group) {
  ASSERT(IsUnmodifiableTypedDataViewClassId(class_id));
  const intptr_t host_instance_size = TypedDataView::InstanceSize();
  const intptr_t target_instance_size = compiler::target::RoundedAllocationSize(
      RTN::TypedDataView::InstanceSize());
  Class& result = Class::Handle(New<TypedDataView, RTN::TypedDataView>(
      class_id, isolate_group, /*register_class=*/false));
  result.set_instance_size(host_instance_size, target_instance_size);

  const intptr_t host_next_field_offset = TypedDataView::NextFieldOffset();
  const intptr_t target_next_field_offset =
      RTN::TypedDataView::NextFieldOffset();
  result.set_next_field_offset(host_next_field_offset,
                               target_next_field_offset);
  result.set_is_prefinalized();
  isolate_group->class_table()->Register(result);
  return result.ptr();
}

ClassPtr Class::NewExternalTypedDataClass(intptr_t class_id,
                                          IsolateGroup* isolate_group) {
  ASSERT(IsExternalTypedDataClassId(class_id));
  const intptr_t host_instance_size = ExternalTypedData::InstanceSize();
  const intptr_t target_instance_size = compiler::target::RoundedAllocationSize(
      RTN::ExternalTypedData::InstanceSize());
  Class& result = Class::Handle(New<ExternalTypedData, RTN::ExternalTypedData>(
      class_id, isolate_group, /*register_class=*/false));

  const intptr_t host_next_field_offset = ExternalTypedData::NextFieldOffset();
  const intptr_t target_next_field_offset =
      RTN::ExternalTypedData::NextFieldOffset();
  result.set_instance_size(host_instance_size, target_instance_size);
  result.set_next_field_offset(host_next_field_offset,
                               target_next_field_offset);
  result.set_is_prefinalized();
  isolate_group->class_table()->Register(result);
  return result.ptr();
}

ClassPtr Class::NewPointerClass(intptr_t class_id,
                                IsolateGroup* isolate_group) {
  ASSERT(IsFfiPointerClassId(class_id));
  intptr_t host_instance_size = Pointer::InstanceSize();
  intptr_t target_instance_size =
      compiler::target::RoundedAllocationSize(RTN::Pointer::InstanceSize());
  Class& result = Class::Handle(New<Pointer, RTN::Pointer>(
      class_id, isolate_group, /*register_class=*/false));
  result.set_instance_size(host_instance_size, target_instance_size);
  result.set_type_arguments_field_offset(Pointer::type_arguments_offset(),
                                         RTN::Pointer::type_arguments_offset());

  const intptr_t host_next_field_offset = Pointer::NextFieldOffset();
  const intptr_t target_next_field_offset = RTN::Pointer::NextFieldOffset();

  result.set_next_field_offset(host_next_field_offset,
                               target_next_field_offset);
  result.set_is_prefinalized();
  isolate_group->class_table()->Register(result);
  return result.ptr();
}

void Class::set_name(const String& value) const {
  ASSERT(untag()->name() == String::null());
  ASSERT(value.IsSymbol());
  untag()->set_name(value.ptr());
#if !defined(PRODUCT)
  if (untag()->user_name() == String::null()) {
    // TODO(johnmccutchan): Eagerly set user name for VM isolate classes,
    // lazily set user name for the other classes.
    // Generate and set user_name.
    const String& user_name = String::Handle(
        Symbols::New(Thread::Current(), GenerateUserVisibleName()));
    set_user_name(user_name);
  }
#endif  // !defined(PRODUCT)
}

#if !defined(PRODUCT)
void Class::set_user_name(const String& value) const {
  untag()->set_user_name(value.ptr());
}
#endif  // !defined(PRODUCT)

#if !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
void Class::SetUserVisibleNameInClassTable() {
  IsolateGroup* isolate_group = IsolateGroup::Current();
  auto class_table = isolate_group->class_table();
  if (class_table->UserVisibleNameFor(id()) == nullptr) {
    String& name = String::Handle(UserVisibleName());
    class_table->SetUserVisibleNameFor(id(), name.ToMallocCString());
  }
}
#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)

const char* Class::GenerateUserVisibleName() const {
  if (FLAG_show_internal_names) {
    return String::Handle(Name()).ToCString();
  }
  switch (id()) {
    case kFloat32x4Cid:
      return Symbols::Float32x4().ToCString();
    case kFloat64x2Cid:
      return Symbols::Float64x2().ToCString();
    case kInt32x4Cid:
      return Symbols::Int32x4().ToCString();
    case kTypedDataInt8ArrayCid:
    case kExternalTypedDataInt8ArrayCid:
      return Symbols::Int8List().ToCString();
    case kTypedDataUint8ArrayCid:
    case kExternalTypedDataUint8ArrayCid:
      return Symbols::Uint8List().ToCString();
    case kTypedDataUint8ClampedArrayCid:
    case kExternalTypedDataUint8ClampedArrayCid:
      return Symbols::Uint8ClampedList().ToCString();
    case kTypedDataInt16ArrayCid:
    case kExternalTypedDataInt16ArrayCid:
      return Symbols::Int16List().ToCString();
    case kTypedDataUint16ArrayCid:
    case kExternalTypedDataUint16ArrayCid:
      return Symbols::Uint16List().ToCString();
    case kTypedDataInt32ArrayCid:
    case kExternalTypedDataInt32ArrayCid:
      return Symbols::Int32List().ToCString();
    case kTypedDataUint32ArrayCid:
    case kExternalTypedDataUint32ArrayCid:
      return Symbols::Uint32List().ToCString();
    case kTypedDataInt64ArrayCid:
    case kExternalTypedDataInt64ArrayCid:
      return Symbols::Int64List().ToCString();
    case kTypedDataUint64ArrayCid:
    case kExternalTypedDataUint64ArrayCid:
      return Symbols::Uint64List().ToCString();
    case kTypedDataInt32x4ArrayCid:
    case kExternalTypedDataInt32x4ArrayCid:
      return Symbols::Int32x4List().ToCString();
    case kTypedDataFloat32x4ArrayCid:
    case kExternalTypedDataFloat32x4ArrayCid:
      return Symbols::Float32x4List().ToCString();
    case kTypedDataFloat64x2ArrayCid:
    case kExternalTypedDataFloat64x2ArrayCid:
      return Symbols::Float64x2List().ToCString();
    case kTypedDataFloat32ArrayCid:
    case kExternalTypedDataFloat32ArrayCid:
      return Symbols::Float32List().ToCString();
    case kTypedDataFloat64ArrayCid:
    case kExternalTypedDataFloat64ArrayCid:
      return Symbols::Float64List().ToCString();
    case kPointerCid:
      return Symbols::FfiPointer().ToCString();
    case kDynamicLibraryCid:
      return Symbols::FfiDynamicLibrary().ToCString();
    case kNullCid:
      return Symbols::Null().ToCString();
    case kDynamicCid:
      return Symbols::Dynamic().ToCString();
    case kVoidCid:
      return Symbols::Void().ToCString();
    case kNeverCid:
      return Symbols::Never().ToCString();
    case kClassCid:
      return Symbols::Class().ToCString();
    case kTypeParametersCid:
      return Symbols::TypeParameters().ToCString();
    case kTypeArgumentsCid:
      return Symbols::TypeArguments().ToCString();
    case kPatchClassCid:
      return Symbols::PatchClass().ToCString();
    case kFunctionCid:
      return Symbols::Function().ToCString();
    case kClosureDataCid:
      return Symbols::ClosureData().ToCString();
    case kFfiTrampolineDataCid:
      return Symbols::FfiTrampolineData().ToCString();
    case kFieldCid:
      return Symbols::Field().ToCString();
    case kScriptCid:
      return Symbols::Script().ToCString();
    case kLibraryCid:
      return Symbols::Library().ToCString();
    case kLibraryPrefixCid:
      return Symbols::LibraryPrefix().ToCString();
    case kNamespaceCid:
      return Symbols::Namespace().ToCString();
    case kKernelProgramInfoCid:
      return Symbols::KernelProgramInfo().ToCString();
    case kWeakSerializationReferenceCid:
      return Symbols::WeakSerializationReference().ToCString();
    case kWeakArrayCid:
      return Symbols::WeakArray().ToCString();
    case kCodeCid:
      return Symbols::Code().ToCString();
    case kBytecodeCid:
      return Symbols::Bytecode().ToCString();
    case kInstructionsCid:
      return Symbols::Instructions().ToCString();
    case kInstructionsSectionCid:
      return Symbols::InstructionsSection().ToCString();
    case kInstructionsTableCid:
      return Symbols::InstructionsTable().ToCString();
    case kObjectPoolCid:
      return Symbols::ObjectPool().ToCString();
    case kCodeSourceMapCid:
      return Symbols::CodeSourceMap().ToCString();
    case kPcDescriptorsCid:
      return Symbols::PcDescriptors().ToCString();
    case kCompressedStackMapsCid:
      return Symbols::CompressedStackMaps().ToCString();
    case kLocalVarDescriptorsCid:
      return Symbols::LocalVarDescriptors().ToCString();
    case kExceptionHandlersCid:
      return Symbols::ExceptionHandlers().ToCString();
    case kContextCid:
      return Symbols::Context().ToCString();
    case kContextScopeCid:
      return Symbols::ContextScope().ToCString();
    case kSentinelCid:
      return Symbols::Sentinel().ToCString();
    case kSingleTargetCacheCid:
      return Symbols::SingleTargetCache().ToCString();
    case kICDataCid:
      return Symbols::ICData().ToCString();
    case kMegamorphicCacheCid:
      return Symbols::MegamorphicCache().ToCString();
    case kSubtypeTestCacheCid:
      return Symbols::SubtypeTestCache().ToCString();
    case kLoadingUnitCid:
      return Symbols::LoadingUnit().ToCString();
    case kApiErrorCid:
      return Symbols::ApiError().ToCString();
    case kLanguageErrorCid:
      return Symbols::LanguageError().ToCString();
    case kUnhandledExceptionCid:
      return Symbols::UnhandledException().ToCString();
    case kUnwindErrorCid:
      return Symbols::UnwindError().ToCString();
    case kIntegerCid:
    case kSmiCid:
    case kMintCid:
      return Symbols::Int().ToCString();
    case kDoubleCid:
      return Symbols::Double().ToCString();
    case kOneByteStringCid:
    case kTwoByteStringCid:
      return Symbols::_String().ToCString();
    case kArrayCid:
    case kImmutableArrayCid:
    case kGrowableObjectArrayCid:
      return Symbols::List().ToCString();
  }
  String& name = String::Handle(Name());
  name = Symbols::New(Thread::Current(), String::ScrubName(name));
  if (name.ptr() == Symbols::_Future().ptr() &&
      library() == Library::AsyncLibrary()) {
    return Symbols::Future().ToCString();
  }
  return name.ToCString();
}

void Class::set_script(const Script& value) const {
  untag()->set_script(value.ptr());
}

#if !defined(DART_PRECOMPILED_RUNTIME)
KernelProgramInfoPtr Class::KernelProgramInfo() const {
  const auto& lib = Library::Handle(library());
  return lib.kernel_program_info();
}

void Class::set_token_pos(TokenPosition token_pos) const {
  ASSERT(!token_pos.IsClassifying());
  StoreNonPointer(&untag()->token_pos_, token_pos);
}

void Class::set_end_token_pos(TokenPosition token_pos) const {
  ASSERT(!token_pos.IsClassifying());
  StoreNonPointer(&untag()->end_token_pos_, token_pos);
}

void Class::set_implementor_cid(intptr_t value) const {
  ASSERT(value >= 0 && value < std::numeric_limits<classid_t>::max());
  StoreNonPointer(&untag()->implementor_cid_, value);
}

void Class::ClearImplementor() const {
  // Check raw implementor_cid_ without normalization done by
  // implementor_cid() accessor.
  if (untag()->implementor_cid_ != kVoidCid) {
    set_implementor_cid(kIllegalCid);
  }
}

bool Class::NoteImplementor(const Class& implementor) const {
  ASSERT(!implementor.is_abstract());
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  if (implementor_cid() == kDynamicCid) {
    return false;
  } else if (implementor_cid() == implementor.id()) {
    return false;
  } else if (implementor_cid() == kIllegalCid) {
    set_implementor_cid(implementor.id());
    return true;  // None -> One
  } else {
    set_implementor_cid(kDynamicCid);
    return true;  // One -> Many
  }
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

uint32_t Class::Hash() const {
  return Class::Hash(ptr());
}
uint32_t Class::Hash(ClassPtr obj) {
  return String::HashRawSymbol(obj.untag()->name());
}

int32_t Class::SourceFingerprint() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (is_declared_in_bytecode()) {
    return 0;
  }
  return kernel::KernelSourceFingerprintHelper::CalculateClassFingerprint(
      *this);
#else
  return 0;
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
}

void Class::set_is_implemented(bool value) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_is_implemented_unsafe(value);
}

void Class::set_is_implemented_unsafe(bool value) const {
  set_state_bits(ImplementedBit::update(value, state_bits()));
}

void Class::set_is_abstract() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(AbstractBit::update(true, state_bits()));
}

void Class::set_is_declaration_loaded() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_is_declaration_loaded_unsafe();
}

void Class::set_is_declaration_loaded_unsafe() const {
  ASSERT(!is_declaration_loaded());
  set_state_bits(ClassLoadingBits::update(UntaggedClass::kDeclarationLoaded,
                                          state_bits()));
}

void Class::set_is_type_finalized() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  ASSERT(is_declaration_loaded());
  ASSERT(!is_type_finalized());
  set_state_bits(
      ClassLoadingBits::update(UntaggedClass::kTypeFinalized, state_bits()));
}

void Class::set_is_synthesized_class() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_is_synthesized_class_unsafe();
}

void Class::set_is_synthesized_class_unsafe() const {
  set_state_bits(SynthesizedClassBit::update(true, state_bits()));
}

void Class::set_is_enum_class() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(EnumBit::update(true, state_bits()));
}

void Class::set_is_const() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(ConstBit::update(true, state_bits()));
}

void Class::set_is_transformed_mixin_application() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(TransformedMixinApplicationBit::update(true, state_bits()));
}

void Class::set_is_sealed() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(SealedBit::update(true, state_bits()));
}

void Class::set_is_mixin_class() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(MixinClassBit::update(true, state_bits()));
}

void Class::set_is_base_class() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(BaseClassBit::update(true, state_bits()));
}

void Class::set_is_interface_class() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(InterfaceClassBit::update(true, state_bits()));
}

void Class::set_is_final() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(FinalBit::update(true, state_bits()));
}

void Class::set_is_fields_marked_nullable() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(FieldsMarkedNullableBit::update(true, state_bits()));
}

void Class::set_is_allocated(bool value) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_is_allocated_unsafe(value);
}

void Class::set_is_allocated_unsafe(bool value) const {
  set_state_bits(IsAllocatedBit::update(value, state_bits()));
}

void Class::set_is_loaded(bool value) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(IsLoadedBit::update(value, state_bits()));
}

#if defined(DART_DYNAMIC_MODULES)
void Class::set_is_declared_in_bytecode(bool value) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_state_bits(IsDeclaredInBytecodeBit::update(value, state_bits()));
}
#endif  // defined(DART_DYNAMIC_MODULES)

void Class::set_is_finalized() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  ASSERT(!is_finalized());
  set_is_finalized_unsafe();
}

void Class::set_is_finalized_unsafe() const {
  set_state_bits(
      ClassFinalizedBits::update(UntaggedClass::kFinalized, state_bits()));
}

void Class::set_is_allocate_finalized() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  ASSERT(!is_allocate_finalized());
  set_state_bits(ClassFinalizedBits::update(UntaggedClass::kAllocateFinalized,
                                            state_bits()));
}

void Class::set_is_prefinalized() const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  ASSERT(!is_finalized());
  set_state_bits(
      ClassFinalizedBits::update(UntaggedClass::kPreFinalized, state_bits()));
}

void Class::set_interfaces(const Array& value) const {
  ASSERT(!value.IsNull());
  untag()->set_interfaces(value.ptr());
}

#if !defined(DART_PRECOMPILED_RUNTIME)

void Class::AddDirectImplementor(const Class& implementor,
                                 bool is_mixin) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  ASSERT(is_implemented());
  ASSERT(!implementor.IsNull());
  GrowableObjectArray& direct_implementors =
      GrowableObjectArray::Handle(untag()->direct_implementors());
  if (direct_implementors.IsNull()) {
    direct_implementors = GrowableObjectArray::New(4, Heap::kOld);
    untag()->set_direct_implementors(direct_implementors.ptr());
  }
#if defined(DEBUG)
  // Verify that the same class is not added twice.
  // The only exception is mixins: when mixin application is transformed,
  // mixin is added to the end of interfaces list and may be duplicated:
  //   class X = A with B implements B;
  // This is rare and harmless.
  if (!is_mixin) {
    for (intptr_t i = 0; i < direct_implementors.Length(); i++) {
      ASSERT(direct_implementors.At(i) != implementor.ptr());
    }
  }
#endif
  direct_implementors.Add(implementor, Heap::kOld);
}

void Class::set_direct_implementors(
    const GrowableObjectArray& implementors) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  untag()->set_direct_implementors(implementors.ptr());
}

void Class::AddDirectSubclass(const Class& subclass) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  ASSERT(!subclass.IsNull());
  ASSERT(subclass.SuperClass() == ptr());
  // Do not keep track of the direct subclasses of class Object.
  ASSERT(!IsObjectClass());
  GrowableObjectArray& direct_subclasses =
      GrowableObjectArray::Handle(untag()->direct_subclasses());
  if (direct_subclasses.IsNull()) {
    direct_subclasses = GrowableObjectArray::New(4, Heap::kOld);
    untag()->set_direct_subclasses(direct_subclasses.ptr());
  }
#if defined(DEBUG)
  // Verify that the same class is not added twice.
  for (intptr_t i = 0; i < direct_subclasses.Length(); i++) {
    ASSERT(direct_subclasses.At(i) != subclass.ptr());
  }
#endif
  direct_subclasses.Add(subclass, Heap::kOld);
}

void Class::set_direct_subclasses(const GrowableObjectArray& subclasses) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  untag()->set_direct_subclasses(subclasses.ptr());
}

#endif  // !defined(DART_PRECOMPILED_RUNTIME)

ArrayPtr Class::constants() const {
  return untag()->constants();
}

void Class::set_constants(const Array& value) const {
  untag()->set_constants(value.ptr());
}

void Class::set_declaration_type(const Type& value) const {
  ASSERT(id() != kDynamicCid && id() != kVoidCid);
  ASSERT(!value.IsNull() && value.IsCanonical() && value.IsOld());
  ASSERT((declaration_type() == Object::null()) ||
         (declaration_type() == value.ptr()));  // Set during own finalization.
  // Since DeclarationType is used as the runtime type of instances of a
  // non-generic class, its nullability must be kNonNullable.
  // The exception is DeclarationType of Null which is kNullable.
  ASSERT(value.type_class_id() != kNullCid || value.IsNullable());
  ASSERT(value.type_class_id() == kNullCid || value.IsNonNullable());
  untag()->set_declaration_type<std::memory_order_release>(value.ptr());
}

TypePtr Class::DeclarationType() const {
  ASSERT(is_declaration_loaded());
  if (IsNullClass()) {
    return Type::NullType();
  }
  if (IsDynamicClass()) {
    return Type::DynamicType();
  }
  if (IsVoidClass()) {
    return Type::VoidType();
  }
  if (declaration_type() != Type::null()) {
    return declaration_type();
  }
  {
    auto thread = Thread::Current();
    SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
    if (declaration_type() != Type::null()) {
      return declaration_type();
    }
    // For efficiency, the runtimeType intrinsic returns the type cached by
    // DeclarationType without checking its nullability. Therefore, we
    // consistently cache the kNonNullable version of the type.
    // The exception is type Null which is stored as kNullable.
    TypeArguments& type_args = TypeArguments::Handle();
    const intptr_t num_type_params = 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 = TypeParameterAt(i);
        type_args.SetTypeAt(i, type_param);
      }
    }
    Type& type =
        Type::Handle(Type::New(*this, type_args, Nullability::kNonNullable));
    type ^= ClassFinalizer::FinalizeType(type);
    set_declaration_type(type);
    return type.ptr();
  }
}

#if !defined(DART_PRECOMPILED_RUNTIME)
void Class::set_allocation_stub(const Code& value) const {
  // Never clear the stub as it may still be a target, but will be GC-d if
  // not referenced.
  ASSERT(!value.IsNull());
  ASSERT(untag()->allocation_stub() == Code::null());
  untag()->set_allocation_stub(value.ptr());
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

void Class::DisableAllocationStub() const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  {
    const Code& existing_stub = Code::Handle(allocation_stub());
    if (existing_stub.IsNull()) {
      return;
    }
  }
  auto thread = Thread::Current();
  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
  const Code& existing_stub = Code::Handle(allocation_stub());
  if (existing_stub.IsNull()) {
    return;
  }
  ASSERT(!existing_stub.IsDisabled());
  // Change the stub so that the next caller will regenerate the stub.
  existing_stub.DisableStubCode(NumTypeParameters() > 0);
  // Disassociate the existing stub from class.
  untag()->set_allocation_stub(Code::null());
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

bool Class::IsDartFunctionClass() const {
  return ptr() == Type::Handle(Type::DartFunctionType()).type_class();
}

bool Class::IsFutureClass() const {
  // Looking up future_class in the object store would not work, because
  // this function is called during class finalization, before the object store
  // field would be initialized by InitKnownObjects().
  return (Name() == Symbols::Future().ptr()) &&
         (library() == Library::AsyncLibrary());
}

// Checks if type T0 is a subtype of type T1.
// Type T0 is specified by class 'cls' parameterized with 'type_arguments' and
// by 'nullability', and type T1 is specified by 'other' and must have a type
// class.
// [type_arguments] should be a flattened instance type arguments vector.
bool Class::IsSubtypeOf(const Class& cls,
                        const TypeArguments& type_arguments,
                        Nullability nullability,
                        const AbstractType& other,
                        Heap::Space space,
                        FunctionTypeMapping* function_type_equivalence) {
  TRACE_TYPE_CHECKS_VERBOSE("  Class::IsSubtypeOf(%s %s, %s)\n",
                            cls.ToCString(), type_arguments.ToCString(),
                            other.ToCString());
  // This function does not support Null, Never, dynamic, or void as type T0.
  classid_t this_cid = cls.id();
  ASSERT(this_cid != kNullCid && this_cid != kNeverCid &&
         this_cid != kDynamicCid && this_cid != kVoidCid);
  ASSERT(type_arguments.IsNull() ||
         (type_arguments.Length() >= cls.NumTypeArguments()));
  // Type T1 must have a type class (e.g. not a type param or a function type).
  ASSERT(other.HasTypeClass());
  const classid_t other_cid = other.type_class_id();
  if (other_cid == kDynamicCid || other_cid == kVoidCid) {
    TRACE_TYPE_CHECKS_VERBOSE("   - result: true (right is top)\n");
    return true;
  }
  // Left nullable:
  //   if T0 is S0? then:
  //     T0 <: T1 iff S0 <: T1 and Null <: T1
  if ((nullability == Nullability::kNullable) &&
      !Instance::NullIsAssignableTo(other)) {
    TRACE_TYPE_CHECKS_VERBOSE("   - result: false (nullability)\n");
    return false;
  }

  // Right Object.
  if (other_cid == kObjectCid) {
    TRACE_TYPE_CHECKS_VERBOSE("   - result: true (right is Object)\n");
    return true;
  }

  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const Class& other_class = Class::Handle(zone, other.type_class());
  const TypeArguments& other_type_arguments =
      TypeArguments::Handle(zone, other.arguments());
  // Use the 'this_class' object as if it was the receiver of this method, but
  // instead of recursing, reset it to the super class and loop.
  Class& this_class = Class::Handle(zone, cls.ptr());
  while (true) {
    // Apply additional subtyping rules if T0 or T1 are 'FutureOr'.

    // Left FutureOr:
    //   if T0 is FutureOr<S0> then:
    //     T0 <: T1 iff Future<S0> <: T1 and S0 <: T1
    if (this_cid == kFutureOrCid) {
      // Check Future<S0> <: T1.
      ObjectStore* object_store = IsolateGroup::Current()->object_store();
      const Class& future_class =
          Class::Handle(zone, object_store->future_class());
      ASSERT(!future_class.IsNull() && future_class.NumTypeParameters() == 1 &&
             this_class.NumTypeParameters() == 1);
      ASSERT(type_arguments.IsNull() || type_arguments.Length() >= 1);
      if (Class::IsSubtypeOf(future_class, type_arguments,
                             Nullability::kNonNullable, other, space,
                             function_type_equivalence)) {
        // Check S0 <: T1.
        const AbstractType& type_arg =
            AbstractType::Handle(zone, type_arguments.TypeAtNullSafe(0));
        if (type_arg.IsSubtypeOf(other, space, function_type_equivalence)) {
          TRACE_TYPE_CHECKS_VERBOSE("   - result: true (left is FutureOr)\n");
          return true;
        }
      }
    }

    // Right FutureOr:
    //   if T1 is FutureOr<S1> then:
    //     T0 <: T1 iff any of the following hold:
    //     either T0 <: Future<S1>
    //     or T0 <: S1
    //     or T0 is X0 and X0 has bound S0 and S0 <: T1  (checked elsewhere)
    if (other_cid == kFutureOrCid) {
      const AbstractType& other_type_arg =
          AbstractType::Handle(zone, other_type_arguments.TypeAtNullSafe(0));
      // Check if S1 is a top type.
      if (other_type_arg.IsTopTypeForSubtyping()) {
        TRACE_TYPE_CHECKS_VERBOSE(
            "   - result: true (right is FutureOr top)\n");
        return true;
      }
      // Check T0 <: Future<S1> when T0 is Future<S0>.
      if (this_class.IsFutureClass()) {
        const AbstractType& type_arg =
            AbstractType::Handle(zone, type_arguments.TypeAtNullSafe(0));
        // If T0 is Future<S0>, then T0 <: Future<S1>, iff S0 <: S1.
        if (type_arg.IsSubtypeOf(other_type_arg, space,
                                 function_type_equivalence)) {
          TRACE_TYPE_CHECKS_VERBOSE(
              "   - result: true (left is Future, right is FutureOr)\n");
          return true;
        }
      }
      // Check T0 <: Future<S1> when T0 is FutureOr<S0> is already done.
      // Check T0 <: S1.
      if (other_type_arg.HasTypeClass() &&
          Class::IsSubtypeOf(this_class, type_arguments, nullability,
                             other_type_arg, space,
                             function_type_equivalence)) {
        TRACE_TYPE_CHECKS_VERBOSE(
            "   - result: true (right is FutureOr, subtype of arg)\n");
        return true;
      }
    }

    // Check for reflexivity.
    if (this_class.ptr() == other_class.ptr()) {
      const intptr_t num_type_params = this_class.NumTypeParameters();
      if (num_type_params == 0) {
        TRACE_TYPE_CHECKS_VERBOSE(
            "   - result: true (same non-generic class)\n");
        return true;
      }
      // Check for covariance.
      if (other_type_arguments.IsNull()) {
        TRACE_TYPE_CHECKS_VERBOSE(
            "   - result: true (same class, dynamic type args)\n");
        return true;
      }
      const intptr_t num_type_args = this_class.NumTypeArguments();
      const intptr_t from_index = num_type_args - num_type_params;
      ASSERT(other_type_arguments.Length() == num_type_params);
      AbstractType& type = AbstractType::Handle(zone);
      AbstractType& other_type = AbstractType::Handle(zone);
      for (intptr_t i = 0; i < num_type_params; ++i) {
        type = type_arguments.TypeAtNullSafe(from_index + i);
        other_type = other_type_arguments.TypeAt(i);
        ASSERT(!type.IsNull() && !other_type.IsNull());
        if (!type.IsSubtypeOf(other_type, space, function_type_equivalence)) {
          TRACE_TYPE_CHECKS_VERBOSE(
              "   - result: false (same class, type args mismatch)\n");
          return false;
        }
      }
      TRACE_TYPE_CHECKS_VERBOSE(
          "   - result: true (same class, matching type args)\n");
      return true;
    }

    // _Closure <: Function
    if (this_class.IsClosureClass() && other_class.IsDartFunctionClass()) {
      TRACE_TYPE_CHECKS_VERBOSE(
          "   - result: true (left is closure, right is Function)\n");
      return true;
    }

    // Check for 'direct super type' specified in the implements clause
    // and check for transitivity at the same time.
    Array& interfaces = Array::Handle(zone, this_class.interfaces());
    Type& interface = Type::Handle(zone);
    Class& interface_class = Class::Handle(zone);
    TypeArguments& interface_args = TypeArguments::Handle(zone);
    for (intptr_t i = 0; i < interfaces.Length(); i++) {
      interface ^= interfaces.At(i);
      ASSERT(interface.IsFinalized());
      interface_class = interface.type_class();
      interface_args = interface.arguments();
      if (!interface_args.IsNull() && !interface_args.IsInstantiated()) {
        // This type class implements an interface that is parameterized with
        // generic type(s), e.g. it implements List<T>.
        // The uninstantiated type T must be instantiated using the type
        // parameters of this type before performing the type test.
        // The type arguments of this type that are referred to by the type
        // parameters of the interface are at the end of the type vector,
        // after the type arguments of the super type of this type.
        // The index of the type parameters is adjusted upon finalization.
        interface_args = interface_args.InstantiateFrom(
            type_arguments, Object::null_type_arguments(), kNoneFree, space);
      }
      interface_args = interface_class.GetInstanceTypeArguments(
          thread, interface_args, /*canonicalize=*/false);
      // In Dart 2, implementing Function has no meaning.
      // TODO(regis): Can we encounter and skip Object as well?
      if (interface_class.IsDartFunctionClass()) {
        continue;
      }
      if (Class::IsSubtypeOf(interface_class, interface_args,
                             Nullability::kNonNullable, other, space,
                             function_type_equivalence)) {
        TRACE_TYPE_CHECKS_VERBOSE("   - result: true (interface found)\n");
        return true;
      }
    }
    // "Recurse" up the class hierarchy until we have reached the top.
    this_class = this_class.SuperClass();
    if (this_class.IsNull()) {
      TRACE_TYPE_CHECKS_VERBOSE("   - result: false (supertype not found)\n");
      return false;
    }
    this_cid = this_class.id();
  }
  UNREACHABLE();
  return false;
}

bool Class::IsTopLevel() const {
  return Name() == Symbols::TopLevel().ptr();
}

bool Class::IsPrivate() const {
  return Library::IsPrivate(String::Handle(Name()));
}

FunctionPtr Class::LookupDynamicFunctionUnsafe(const String& name) const {
  return LookupFunctionReadLocked(name, kInstance);
}

FunctionPtr Class::LookupDynamicFunctionAllowPrivate(const String& name) const {
  return LookupFunctionAllowPrivate(name, kInstance);
}

FunctionPtr Class::LookupStaticFunction(const String& name) const {
  Thread* thread = Thread::Current();
  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
  return LookupFunctionReadLocked(name, kStatic);
}

FunctionPtr Class::LookupStaticFunctionAllowPrivate(const String& name) const {
  return LookupFunctionAllowPrivate(name, kStatic);
}

FunctionPtr Class::LookupConstructor(const String& name) const {
  Thread* thread = Thread::Current();
  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
  return LookupFunctionReadLocked(name, kConstructor);
}

FunctionPtr Class::LookupConstructorAllowPrivate(const String& name) const {
  return LookupFunctionAllowPrivate(name, kConstructor);
}

FunctionPtr Class::LookupFactory(const String& name) const {
  Thread* thread = Thread::Current();
  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
  return LookupFunctionReadLocked(name, kFactory);
}

FunctionPtr Class::LookupFactoryAllowPrivate(const String& name) const {
  return LookupFunctionAllowPrivate(name, kFactory);
}

FunctionPtr Class::LookupFunctionAllowPrivate(const String& name) const {
  return LookupFunctionAllowPrivate(name, kAny);
}

FunctionPtr Class::LookupFunctionReadLocked(const String& name) const {
  return LookupFunctionReadLocked(name, kAny);
}

// Returns true if 'prefix' and 'accessor_name' match 'name'.
static bool MatchesAccessorName(const String& name,
                                const char* prefix,
                                intptr_t prefix_length,
                                const String& accessor_name) {
  intptr_t name_len = name.Length();
  intptr_t accessor_name_len = accessor_name.Length();

  if (name_len != (accessor_name_len + prefix_length)) {
    return false;
  }
  for (intptr_t i = 0; i < prefix_length; i++) {
    if (name.CharAt(i) != prefix[i]) {
      return false;
    }
  }
  for (intptr_t i = 0, j = prefix_length; i < accessor_name_len; i++, j++) {
    if (name.CharAt(j) != accessor_name.CharAt(i)) {
      return false;
    }
  }
  return true;
}

FunctionPtr Class::CheckFunctionType(const Function& func, MemberKind kind) {
  if ((kind == kInstance) || (kind == kInstanceAllowAbstract)) {
    if (func.IsDynamicFunction(kind == kInstanceAllowAbstract)) {
      return func.ptr();
    }
  } else if (kind == kStatic) {
    if (func.IsStaticFunction()) {
      return func.ptr();
    }
  } else if (kind == kConstructor) {
    if (func.IsGenerativeConstructor()) {
      ASSERT(!func.is_static());
      return func.ptr();
    }
  } else if (kind == kFactory) {
    if (func.IsFactory()) {
      ASSERT(func.is_static());
      return func.ptr();
    }
  } else if (kind == kAny) {
    return func.ptr();
  }
  return Function::null();
}

FunctionPtr Class::LookupFunctionReadLocked(const String& name,
                                            MemberKind kind) const {
  ASSERT(!IsNull());
  Thread* thread = Thread::Current();
  RELEASE_ASSERT(is_finalized());
  // Caller needs to ensure they grab program_lock because this method
  // can be invoked with either ReadRwLock or WriteRwLock.
#if defined(DEBUG)
  ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadReader());
#endif
  ASSERT(functions() != Array::null());
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_FUNCTION_HANDLESCOPE(thread);
  Array& funcs = thread->ArrayHandle();
  funcs = functions();
  const intptr_t len = funcs.Length();
  Function& function = thread->FunctionHandle();
  if (len >= kFunctionLookupHashThreshold) {
    // TODO(dartbug.com/36097): We require currently a read lock in the resolver
    // to avoid read-write race access to this hash table.
    // If we want to increase resolver speed by avoiding the need for read lock,
    // we could make change this hash table to be lock-free for the reader.
    const Array& hash_table =
        Array::Handle(thread->zone(), untag()->functions_hash_table());
    if (!hash_table.IsNull()) {
      ClassFunctionsSet set(hash_table.ptr());
      REUSABLE_STRING_HANDLESCOPE(thread);
      function ^= set.GetOrNull(FunctionName(name, &(thread->StringHandle())));
      // No mutations.
      ASSERT(set.Release().ptr() == hash_table.ptr());
      return function.IsNull() ? Function::null()
                               : CheckFunctionType(function, kind);
    }
  }
  if (name.IsSymbol()) {
    // Quick Symbol compare.
    NoSafepointScope no_safepoint;
    for (intptr_t i = 0; i < len; i++) {
      function ^= funcs.At(i);
      if (function.name() == name.ptr()) {
        return CheckFunctionType(function, kind);
      }
    }
  } else {
    REUSABLE_STRING_HANDLESCOPE(thread);
    String& function_name = thread->StringHandle();
    for (intptr_t i = 0; i < len; i++) {
      function ^= funcs.At(i);
      function_name = function.name();
      if (function_name.Equals(name)) {
        return CheckFunctionType(function, kind);
      }
    }
  }
  // No function found.
  return Function::null();
}

FunctionPtr Class::LookupFunctionAllowPrivate(const String& name,
                                              MemberKind kind) const {
  ASSERT(!IsNull());
  Thread* thread = Thread::Current();
  RELEASE_ASSERT(is_finalized());
  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_FUNCTION_HANDLESCOPE(thread);
  REUSABLE_STRING_HANDLESCOPE(thread);
  Array& funcs = thread->ArrayHandle();
  funcs = current_functions();
  ASSERT(!funcs.IsNull());
  const intptr_t len = funcs.Length();
  Function& function = thread->FunctionHandle();
  String& function_name = thread->StringHandle();
  for (intptr_t i = 0; i < len; i++) {
    function ^= funcs.At(i);
    function_name = function.name();
    if (String::EqualsIgnoringPrivateKey(function_name, name)) {
      return CheckFunctionType(function, kind);
    }
  }
  // No function found.
  return Function::null();
}

FunctionPtr Class::LookupGetterFunction(const String& name) const {
  return LookupAccessorFunction(kGetterPrefix, kGetterPrefixLength, name);
}

FunctionPtr Class::LookupSetterFunction(const String& name) const {
  return LookupAccessorFunction(kSetterPrefix, kSetterPrefixLength, name);
}

FunctionPtr Class::LookupAccessorFunction(const char* prefix,
                                          intptr_t prefix_length,
                                          const String& name) const {
  ASSERT(!IsNull());
  Thread* thread = Thread::Current();
  if (EnsureIsFinalized(thread) != Error::null()) {
    return Function::null();
  }
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_FUNCTION_HANDLESCOPE(thread);
  REUSABLE_STRING_HANDLESCOPE(thread);
  Array& funcs = thread->ArrayHandle();
  funcs = current_functions();
  intptr_t len = funcs.Length();
  Function& function = thread->FunctionHandle();
  String& function_name = thread->StringHandle();
  for (intptr_t i = 0; i < len; i++) {
    function ^= funcs.At(i);
    function_name = function.name();
    if (MatchesAccessorName(function_name, prefix, prefix_length, name)) {
      return function.ptr();
    }
  }

  // No function found.
  return Function::null();
}

FieldPtr Class::LookupInstanceField(const String& name) const {
  return LookupField(name, kInstance);
}

FieldPtr Class::LookupStaticField(const String& name) const {
  return LookupField(name, kStatic);
}

FieldPtr Class::LookupField(const String& name) const {
  return LookupField(name, kAny);
}

FieldPtr Class::LookupField(const String& name, MemberKind kind) const {
  ASSERT(!IsNull());
  Thread* thread = Thread::Current();
  if (EnsureIsFinalized(thread) != Error::null()) {
    return Field::null();
  }
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_FIELD_HANDLESCOPE(thread);
  REUSABLE_STRING_HANDLESCOPE(thread);
  Array& flds = thread->ArrayHandle();
  flds = fields();
  ASSERT(!flds.IsNull());
  intptr_t len = flds.Length();
  Field& field = thread->FieldHandle();
  if (name.IsSymbol()) {
    // Use fast raw pointer string compare for symbols.
    for (intptr_t i = 0; i < len; i++) {
      field ^= flds.At(i);
      if (name.ptr() == field.name()) {
        if (kind == kInstance) {
          return field.is_static() ? Field::null() : field.ptr();
        } else if (kind == kStatic) {
          return field.is_static() ? field.ptr() : Field::null();
        }
        ASSERT(kind == kAny);
        return field.ptr();
      }
    }
  } else {
    String& field_name = thread->StringHandle();
    for (intptr_t i = 0; i < len; i++) {
      field ^= flds.At(i);
      field_name = field.name();
      if (name.Equals(field_name)) {
        if (kind == kInstance) {
          return field.is_static() ? Field::null() : field.ptr();
        } else if (kind == kStatic) {
          return field.is_static() ? field.ptr() : Field::null();
        }
        ASSERT(kind == kAny);
        return field.ptr();
      }
    }
  }
  return Field::null();
}

FieldPtr Class::LookupFieldAllowPrivate(const String& name,
                                        bool instance_only) const {
  ASSERT(!IsNull());
  // Use slow string compare, ignoring privacy name mangling.
  Thread* thread = Thread::Current();
  if (EnsureIsFinalized(thread) != Error::null()) {
    return Field::null();
  }
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_FIELD_HANDLESCOPE(thread);
  REUSABLE_STRING_HANDLESCOPE(thread);
  Array& flds = thread->ArrayHandle();
  flds = fields();
  ASSERT(!flds.IsNull());
  intptr_t len = flds.Length();
  Field& field = thread->FieldHandle();
  String& field_name = thread->StringHandle();
  for (intptr_t i = 0; i < len; i++) {
    field ^= flds.At(i);
    field_name = field.name();
    if (field.is_static() && instance_only) {
      // If we only care about instance fields, skip statics.
      continue;
    }
    if (String::EqualsIgnoringPrivateKey(field_name, name)) {
      return field.ptr();
    }
  }
  return Field::null();
}

FieldPtr Class::LookupInstanceFieldAllowPrivate(const String& name) const {
  Field& field = Field::Handle(LookupFieldAllowPrivate(name, true));
  if (!field.IsNull() && !field.is_static()) {
    return field.ptr();
  }
  return Field::null();
}

FieldPtr Class::LookupStaticFieldAllowPrivate(const String& name) const {
  Field& field = Field::Handle(LookupFieldAllowPrivate(name));
  if (!field.IsNull() && field.is_static()) {
    return field.ptr();
  }
  return Field::null();
}

const char* Class::ToCString() const {
  ZoneTextBuffer buffer(Thread::Current()->zone());
  const Library& lib = Library::Handle(library());
  if (!lib.IsNull()) {
    buffer.Printf("%s ", lib.ToCString());
  }
  buffer.Printf("Class: %s", String::Handle(Name()).ToCString());
  return buffer.buffer();
}

// Thomas Wang, Integer Hash Functions.
// https://gist.github.com/badboy/6267743
// "64 bit to 32 bit Hash Functions"
static uword Hash64To32(uint64_t v) {
  v = ~v + (v << 18);
  v = v ^ (v >> 31);
  v = v * 21;
  v = v ^ (v >> 11);
  v = v + (v << 6);
  v = v ^ (v >> 22);
  return static_cast<uint32_t>(v);
}

InstancePtr Class::LookupCanonicalInstance(Zone* zone,
                                           const Instance& value) const {
  ASSERT(this->ptr() == value.clazz());
  ASSERT(is_finalized() || is_prefinalized());
  Instance& canonical_value = Instance::Handle(zone);
  if (this->constants() != Array::null()) {
    CanonicalInstancesSet constants(zone, this->constants());
    canonical_value ^= constants.GetOrNull(CanonicalInstanceKey(value));
    this->set_constants(constants.Release());
  }
  return canonical_value.ptr();
}

InstancePtr Class::InsertCanonicalConstant(Zone* zone,
                                           const Instance& constant) const {
  ASSERT(constant.IsCanonical());
  ASSERT(this->ptr() == constant.clazz());
  Instance& canonical_value = Instance::Handle(zone);
  if (this->constants() == Array::null()) {
    CanonicalInstancesSet constants(
        HashTables::New<CanonicalInstancesSet>(128, Heap::kOld));
    canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant));
    this->set_constants(constants.Release());
  } else {
    CanonicalInstancesSet constants(Thread::Current()->zone(),
                                    this->constants());
    canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant));
    this->set_constants(constants.Release());
  }
  return canonical_value.ptr();
}

// Scoped mapping FunctionType -> FunctionType.
// Used for tracking and updating nested generic function types
// and their type parameters.
class FunctionTypeMapping : public ValueObject {
 public:
  FunctionTypeMapping(Zone* zone,
                      FunctionTypeMapping** mapping,
                      const FunctionType& from,
                      const FunctionType& to)
      : zone_(zone), parent_(*mapping), from_(from), to_(to) {
    // Add self to the linked list.
    *mapping = this;
  }

  const FunctionType* Find(const Object& from) const {
    if (!from.IsFunctionType()) {
      return nullptr;
    }
    for (const FunctionTypeMapping* scope = this; scope != nullptr;
         scope = scope->parent_) {
      if (scope->from_.ptr() == from.ptr()) {
        return &(scope->to_);
      }
    }
    return nullptr;
  }

  TypeParameterPtr MapTypeParameter(const TypeParameter& type_param) const {
    ASSERT(type_param.IsFunctionTypeParameter());
    const FunctionType* new_owner = Find(
        FunctionType::Handle(zone_, type_param.parameterized_function_type()));
    if (new_owner != nullptr) {
      return new_owner->TypeParameterAt(type_param.index() - type_param.base(),
                                        type_param.nullability());
    }
    return type_param.ptr();
  }

  bool ContainsOwnersOfTypeParameters(const TypeParameter& p1,
                                      const TypeParameter& p2) const {
    auto& from = FunctionType::Handle(zone_, p1.parameterized_function_type());
    const FunctionType* to = Find(from);
    if (to != nullptr) {
      return to->ptr() == p2.parameterized_function_type();
    }
    from = p2.parameterized_function_type();
    to = Find(from);
    if (to != nullptr) {
      return to->ptr() == p1.parameterized_function_type();
    }
    return false;
  }

 private:
  Zone* zone_;
  const FunctionTypeMapping* const parent_;
  const FunctionType& from_;
  const FunctionType& to_;
};

intptr_t TypeParameters::Length() const {
  if (IsNull() || untag()->names() == Array::null()) return 0;
  return Smi::Value(untag()->names()->untag()->length());
}

void TypeParameters::set_names(const Array& value) const {
  ASSERT(!value.IsNull());
  untag()->set_names(value.ptr());
}

StringPtr TypeParameters::NameAt(intptr_t index) const {
  const Array& names_array = Array::Handle(names());
  return String::RawCast(names_array.At(index));
}

void TypeParameters::SetNameAt(intptr_t index, const String& value) const {
  const Array& names_array = Array::Handle(names());
  names_array.SetAt(index, value);
}

void TypeParameters::set_flags(const Array& value) const {
  untag()->set_flags(value.ptr());
}

void TypeParameters::set_bounds(const TypeArguments& value) const {
  // A null value represents a vector of dynamic.
  untag()->set_bounds(value.ptr());
}

AbstractTypePtr TypeParameters::BoundAt(intptr_t index) const {
  const TypeArguments& upper_bounds = TypeArguments::Handle(bounds());
  return upper_bounds.IsNull() ? Type::DynamicType()
                               : upper_bounds.TypeAt(index);
}

void TypeParameters::SetBoundAt(intptr_t index,
                                const AbstractType& value) const {
  const TypeArguments& upper_bounds = TypeArguments::Handle(bounds());
  upper_bounds.SetTypeAt(index, value);
}

bool TypeParameters::AllDynamicBounds() const {
  return bounds() == TypeArguments::null();
}

void TypeParameters::set_defaults(const TypeArguments& value) const {
  // The null value represents a vector of dynamic.
  untag()->set_defaults(value.ptr());
}

AbstractTypePtr TypeParameters::DefaultAt(intptr_t index) const {
  const TypeArguments& default_type_args = TypeArguments::Handle(defaults());
  return default_type_args.IsNull() ? Type::DynamicType()
                                    : default_type_args.TypeAt(index);
}

void TypeParameters::SetDefaultAt(intptr_t index,
                                  const AbstractType& value) const {
  const TypeArguments& default_type_args = TypeArguments::Handle(defaults());
  default_type_args.SetTypeAt(index, value);
}

bool TypeParameters::AllDynamicDefaults() const {
  return defaults() == TypeArguments::null();
}

void TypeParameters::AllocateFlags(Heap::Space space) const {
  const intptr_t len = (Length() + kFlagsPerSmiMask) >> kFlagsPerSmiShift;
  const Array& flags_array = Array::Handle(Array::New(len, space));
  // Initialize flags to 0.
  const Smi& zero = Smi::Handle(Smi::New(0));
  for (intptr_t i = 0; i < len; i++) {
    flags_array.SetAt(i, zero);
  }
  set_flags(flags_array);
}

void TypeParameters::OptimizeFlags() const {
  if (untag()->flags() == Array::null()) return;  // Already optimized.
  const intptr_t len = (Length() + kFlagsPerSmiMask) >> kFlagsPerSmiShift;
  const Array& flags_array = Array::Handle(flags());
  const Smi& zero = Smi::Handle(Smi::New(0));
  for (intptr_t i = 0; i < len; i++) {
    if (flags_array.At(i) != zero.ptr()) return;
  }
  set_flags(Object::null_array());
}

bool TypeParameters::IsGenericCovariantImplAt(intptr_t index) const {
  if (untag()->flags() == Array::null()) return false;
  const intptr_t flag = Smi::Value(
      Smi::RawCast(Array::Handle(flags()).At(index >> kFlagsPerSmiShift)));
  return (flag >> (index & kFlagsPerSmiMask)) != 0;
}

void TypeParameters::SetIsGenericCovariantImplAt(intptr_t index,
                                                 bool value) const {
  const Array& flg = Array::Handle(flags());
  intptr_t flag = Smi::Value(Smi::RawCast(flg.At(index >> kFlagsPerSmiShift)));
  if (value) {
    flag |= 1 << (index % kFlagsPerSmiMask);
  } else {
    flag &= ~(1 << (index % kFlagsPerSmiMask));
  }
  flg.SetAt(index >> kFlagsPerSmiShift, Smi::Handle(Smi::New(flag)));
}

void TypeParameters::Print(Thread* thread,
                           Zone* zone,
                           bool are_class_type_parameters,
                           intptr_t base,
                           NameVisibility name_visibility,
                           BaseTextBuffer* printer) const {
  String& name = String::Handle(zone);
  AbstractType& type = AbstractType::Handle(zone);
  const intptr_t num_type_params = Length();
  for (intptr_t i = 0; i < num_type_params; i++) {
    if (are_class_type_parameters) {
      name = NameAt(i);
      printer->AddString(name.ToCString());
    } else {
      printer->AddString(TypeParameter::CanonicalNameCString(
          are_class_type_parameters, base, base + i));
    }
    if (FLAG_show_internal_names || !AllDynamicBounds()) {
      type = BoundAt(i);
      // Do not print default bound.
      if (!type.IsNull() && (FLAG_show_internal_names || !type.IsObjectType() ||
                             type.IsNonNullable())) {
        printer->AddString(" extends ");
        type.PrintName(name_visibility, printer);
        if (FLAG_show_internal_names && !AllDynamicDefaults()) {
          type = DefaultAt(i);
          if (!type.IsNull() &&
              (FLAG_show_internal_names || !type.IsDynamicType())) {
            printer->AddString(" defaults to ");
            type.PrintName(name_visibility, printer);
          }
        }
      }
    }
    if (i != num_type_params - 1) {
      printer->AddString(", ");
    }
  }
}

const char* TypeParameters::ToCString() const {
  if (IsNull()) {
    return "TypeParameters: null";
  }
  auto thread = Thread::Current();
  auto zone = thread->zone();
  ZoneTextBuffer buffer(zone);
  buffer.AddString("TypeParameters: ");
  Print(thread, zone, true, 0, kInternalName, &buffer);
  return buffer.buffer();
}

TypeParametersPtr TypeParameters::New(Heap::Space space) {
  ASSERT(Object::type_parameters_class() != Class::null());
  return Object::Allocate<TypeParameters>(space);
}

TypeParametersPtr TypeParameters::New(intptr_t count, Heap::Space space) {
  const TypeParameters& result =
      TypeParameters::Handle(TypeParameters::New(space));
  // Create an [ Array ] of [ String ] objects to represent the names.
  // Create a [ TypeArguments ] vector representing the bounds.
  // Create a [ TypeArguments ] vector representing the defaults.
  // Create an [ Array ] of [ Smi] objects to represent the flags.
  const Array& names_array = Array::Handle(Array::New(count, space));
  result.set_names(names_array);
  TypeArguments& type_args = TypeArguments::Handle();
  type_args = TypeArguments::New(count, Heap::kNew);  // Will get canonicalized.
  result.set_bounds(type_args);
  type_args = TypeArguments::New(count, Heap::kNew);  // Will get canonicalized.
  result.set_defaults(type_args);
  result.AllocateFlags(space);  // Will get optimized.
  return result.ptr();
}

intptr_t TypeArguments::ComputeNullability() const {
  if (IsNull()) return 0;
  const intptr_t num_types = Length();
  intptr_t result = 0;
  if (num_types <= kNullabilityMaxTypes) {
    AbstractType& type = AbstractType::Handle();
    for (intptr_t i = 0; i < num_types; i++) {
      type = TypeAt(i);
      intptr_t type_bits = 0;
      if (!type.IsNull()) {
        switch (type.nullability()) {
          case Nullability::kNullable:
            type_bits = kNullableBit;
            break;
          case Nullability::kNonNullable:
            type_bits = kNonNullableBit;
            break;
          default:
            UNREACHABLE();
        }
      }
      result |= (type_bits << (i * kNullabilityBitsPerType));
    }
  }
  set_nullability(result);
  return result;
}

void TypeArguments::set_nullability(intptr_t value) const {
  untag()->set_nullability(Smi::New(value));
}

uword TypeArguments::HashForRange(intptr_t from_index, intptr_t len) const {
  if (IsNull()) return kAllDynamicHash;
  if (IsRaw(from_index, len)) return kAllDynamicHash;
  uint32_t result = 0;
  AbstractType& type = AbstractType::Handle();
  for (intptr_t i = 0; i < len; i++) {
    type = TypeAt(from_index + i);
    ASSERT(!type.IsNull());
    result = CombineHashes(result, type.Hash());
  }
  result = FinalizeHash(result, kHashBits);
  return result;
}

uword TypeArguments::ComputeHash() const {
  if (IsNull()) return kAllDynamicHash;
  const uword result = HashForRange(0, Length());
  ASSERT(result != 0);
  SetHash(result);
  return result;
}

TypeArgumentsPtr TypeArguments::Prepend(Zone* zone,
                                        const TypeArguments& other,
                                        intptr_t other_length,
                                        intptr_t total_length) const {
  if (other_length == 0) {
    ASSERT(IsCanonical());
    return ptr();
  } else if (other_length == total_length) {
    ASSERT(other.IsCanonical());
    return other.ptr();
  } else if (IsNull() && other.IsNull()) {
    return TypeArguments::null();
  }
  const TypeArguments& result =
      TypeArguments::Handle(zone, TypeArguments::New(total_length, Heap::kNew));
  AbstractType& type = AbstractType::Handle(zone);
  for (intptr_t i = 0; i < other_length; i++) {
    type = other.IsNull() ? Type::DynamicType() : other.TypeAt(i);
    result.SetTypeAt(i, type);
  }
  for (intptr_t i = other_length; i < total_length; i++) {
    type = IsNull() ? Type::DynamicType() : TypeAt(i - other_length);
    result.SetTypeAt(i, type);
  }
  return result.Canonicalize(Thread::Current());
}

TypeArgumentsPtr TypeArguments::ConcatenateTypeParameters(
    Zone* zone,
    const TypeArguments& other) const {
  ASSERT(!IsNull() && !other.IsNull());
  const intptr_t this_len = Length();
  const intptr_t other_len = other.Length();
  const auto& result = TypeArguments::Handle(
      zone, TypeArguments::New(this_len + other_len, Heap::kNew));
  auto& type = AbstractType::Handle(zone);
  for (intptr_t i = 0; i < this_len; ++i) {
    type = TypeAt(i);
    result.SetTypeAt(i, type);
  }
  for (intptr_t i = 0; i < other_len; ++i) {
    type = other.TypeAt(i);
    result.SetTypeAt(this_len + i, type);
  }
  return result.ptr();
}

InstantiationMode TypeArguments::GetInstantiationMode(Zone* zone,
                                                      const Function* function,
                                                      const Class* cls) const {
  if (IsNull() || IsInstantiated()) {
    return InstantiationMode::kIsInstantiated;
  }
  if (function != nullptr) {
    if (CanShareFunctionTypeArguments(*function)) {
      return InstantiationMode::kSharesFunctionTypeArguments;
    }
    if (cls == nullptr) {
      cls = &Class::Handle(zone, function->Owner());
    }
  }
  if (cls != nullptr) {
    if (CanShareInstantiatorTypeArguments(*cls)) {
      return InstantiationMode::kSharesInstantiatorTypeArguments;
    }
  }
  return InstantiationMode::kNeedsInstantiation;
}

StringPtr TypeArguments::Name() const {
  Thread* thread = Thread::Current();
  ZoneTextBuffer printer(thread->zone());
  PrintSubvectorName(0, Length(), kInternalName, &printer);
  return Symbols::New(thread, printer.buffer());
}

StringPtr TypeArguments::UserVisibleName() const {
  Thread* thread = Thread::Current();
  ZoneTextBuffer printer(thread->zone());
  PrintSubvectorName(0, Length(), kUserVisibleName, &printer);
  return Symbols::New(thread, printer.buffer());
}

void TypeArguments::PrintSubvectorName(intptr_t from_index,
                                       intptr_t len,
                                       NameVisibility name_visibility,
                                       BaseTextBuffer* printer) const {
  printer->AddString("<");
  AbstractType& type = AbstractType::Handle();
  for (intptr_t i = 0; i < len; i++) {
    if (from_index + i < Length()) {
      type = TypeAt(from_index + i);
      if (type.IsNull()) {
        printer->AddString("null");  // Unfinalized vector.
      } else {
        type.PrintName(name_visibility, printer);
      }
    } else {
      printer->AddString("dynamic");
    }
    if (i < len - 1) {
      printer->AddString(", ");
    }
  }
  printer->AddString(">");
}

void TypeArguments::PrintTo(BaseTextBuffer* buffer) const {
  buffer->AddString("TypeArguments: ");
  if (IsNull()) {
    return buffer->AddString("null");
  }
  buffer->Printf("(H%" Px ")", Smi::Value(untag()->hash()));
  auto& type_at = AbstractType::Handle();
  for (intptr_t i = 0; i < Length(); i++) {
    type_at = TypeAt(i);
    buffer->Printf(" [%s]", type_at.IsNull() ? "null" : type_at.ToCString());
  }
}

bool TypeArguments::IsSubvectorEquivalent(
    const TypeArguments& other,
    intptr_t from_index,
    intptr_t len,
    TypeEquality kind,
    FunctionTypeMapping* function_type_equivalence) const {
  if (this->ptr() == other.ptr()) {
    return true;
  }
  if (kind == TypeEquality::kCanonical) {
    if (IsNull()) {
      return other.IsRaw(from_index, len);
    } else if (other.IsNull()) {
      return IsRaw(from_index, len);
    }
    if (Length() != other.Length()) {
      return false;
    }
  }
  AbstractType& type = AbstractType::Handle();
  AbstractType& other_type = AbstractType::Handle();
  for (intptr_t i = from_index; i < from_index + len; i++) {
    type = IsNull() ? Type::DynamicType() : TypeAt(i);
    ASSERT(!type.IsNull());
    other_type = other.IsNull() ? Type::DynamicType() : other.TypeAt(i);
    ASSERT(!other_type.IsNull());
    if (!type.IsEquivalent(other_type, kind, function_type_equivalence)) {
      return false;
    }
  }
  return true;
}

bool TypeArguments::IsDynamicTypes(bool raw_instantiated,
                                   intptr_t from_index,
                                   intptr_t len) const {
  ASSERT(Length() >= (from_index + len));
  AbstractType& type = AbstractType::Handle();
  Class& type_class = Class::Handle();
  for (intptr_t i = 0; i < len; i++) {
    type = TypeAt(from_index + i);
    if (type.IsNull()) {
      return false;
    }
    if (!type.HasTypeClass()) {
      if (raw_instantiated && type.IsTypeParameter()) {
        // An uninstantiated type parameter is equivalent to dynamic.
        continue;
      }
      return false;
    }
    type_class = type.type_class();
    if (!type_class.IsDynamicClass()) {
      return false;
    }
  }
  return true;
}

TypeArguments::Cache::Cache(Zone* zone, const TypeArguments& source)
    : zone_(ASSERT_NOTNULL(zone)),
      cache_container_(&source),
      data_(Array::Handle(source.instantiations())),
      smi_handle_(Smi::Handle(zone)) {
  ASSERT(IsolateGroup::Current()
             ->type_arguments_canonicalization_mutex()
             ->IsOwnedByCurrentThread());
}

TypeArguments::Cache::Cache(Zone* zone, const Array& array)
    : zone_(ASSERT_NOTNULL(zone)),
      cache_container_(nullptr),
      data_(Array::Handle(array.ptr())),
      smi_handle_(Smi::Handle(zone)) {
  ASSERT(IsolateGroup::Current()
             ->type_arguments_canonicalization_mutex()
             ->IsOwnedByCurrentThread());
}

bool TypeArguments::Cache::IsHash(const Array& array) {
  return array.Length() > kMaxLinearCacheSize;
}

intptr_t TypeArguments::Cache::NumOccupied(const Array& array) {
  return NumOccupiedBits::decode(
      RawSmiValue(Smi::RawCast(array.AtAcquire(kMetadataIndex))));
}

#if defined(DEBUG)
bool TypeArguments::Cache::IsValidStorageLocked(const Array& array) {
  // We only require the mutex be held so we don't need to use acquire/release
  // semantics to access and set the number of occupied entries in the header.
  ASSERT(IsolateGroup::Current()
             ->type_arguments_canonicalization_mutex()
             ->IsOwnedByCurrentThread());
  // Quick check against the empty linear cache.
  if (array.ptr() == EmptyStorage().ptr()) return true;
  const intptr_t num_occupied = NumOccupied(array);
  // We should be using the same shared value for an empty cache.
  if (num_occupied == 0) return false;
  const intptr_t storage_len = array.Length();
  // All caches have the metadata followed by a series of entries.
  if ((storage_len % kEntrySize) != kHeaderSize) return false;
  const intptr_t num_entries = NumEntries(array);
  // Linear caches contain at least one unoccupied entry, and hash-based caches
  // grow prior to hitting 100% occupancy.
  if (num_occupied >= num_entries) return false;
  // In a linear cache, all entries with indexes smaller than [num_occupied]
  // should be occupied and ones greater than or equal should be unoccupied.
  const bool is_linear_cache = IsLinear(array);
  // The capacity of a hash-based cache must be a power of two (see
  // EnsureCapacityLocked as to why).
  if (!is_linear_cache) {
    if (!Utils::IsPowerOfTwo(num_entries)) return false;
    const intptr_t metadata =
        RawSmiValue(Smi::RawCast(array.AtAcquire(kMetadataIndex)));
    if ((1 << EntryCountLog2Bits::decode(metadata)) != num_entries) {
      return false;
    }
  }
  for (intptr_t i = 0; i < num_entries; i++) {
    const intptr_t index = kHeaderSize + i * kEntrySize;
    if (array.At(index + kSentinelIndex) == Sentinel()) {
      if (is_linear_cache && i < num_occupied) return false;
      continue;
    }
    if (is_linear_cache && i >= num_occupied) return false;
    // The elements of an occupied entry are all TypeArguments values.
    for (intptr_t j = index; j < index + kEntrySize; j++) {
      if (!array.At(j)->IsHeapObject()) return false;
      if (array.At(j) == Object::null()) continue;  // null is a valid TAV.
      if (!array.At(j)->IsTypeArguments()) return false;
    }
  }
  return true;
}
#endif

bool TypeArguments::Cache::IsOccupied(intptr_t entry) const {
  InstantiationsCacheTable table(data_);
  ASSERT(entry >= 0 && entry < table.Length());
  return table.At(entry).Get<kSentinelIndex>() != Sentinel();
}

TypeArgumentsPtr TypeArguments::Cache::Retrieve(intptr_t entry) const {
  ASSERT(IsOccupied(entry));
  InstantiationsCacheTable table(data_);
  return table.At(entry).Get<kInstantiatedTypeArgsIndex>();
}

intptr_t TypeArguments::Cache::NumEntries(const Array& array) {
  InstantiationsCacheTable table(array);
  return table.Length();
}

TypeArguments::Cache::KeyLocation TypeArguments::Cache::FindKeyOrUnused(
    const Array& array,
    const TypeArguments& instantiator_tav,
    const TypeArguments& function_tav) {
  const bool is_hash = IsHash(array);
  InstantiationsCacheTable table(array);
  const intptr_t num_entries = table.Length();
  // For a linear cache, start at the first entry and probe linearly. This can
  // be done because a linear cache always has at least one unoccupied entry
  // after all the occupied ones.
  intptr_t probe = 0;
  intptr_t probe_distance = 1;
  if (is_hash) {
    // For a hash-based cache, instead start at an entry determined by the hash
    // of the keys.
    auto hash = FinalizeHash(
        CombineHashes(instantiator_tav.Hash(), function_tav.Hash()));
    probe = hash & (num_entries - 1);
  }
  while (true) {
    const auto& tuple = table.At(probe);
    if (tuple.Get<kSentinelIndex>() == Sentinel()) break;
    if ((tuple.Get<kInstantiatorTypeArgsIndex>() == instantiator_tav.ptr()) &&
        (tuple.Get<kFunctionTypeArgsIndex>() == function_tav.ptr())) {
      return {probe, true};
    }
    // Advance probe by the current probing distance.
    probe = probe + probe_distance;
    if (is_hash) {
      // Wrap around if the probe goes off the end of the entries array.
      probe = probe & (num_entries - 1);
      // We had a collision, so increase the probe distance. See comment in
      // EnsureCapacityLocked for an explanation of how this hits all slots.
      probe_distance++;
    }
  }
  // We should always get the next slot for a linear cache.
  ASSERT(is_hash || probe == NumOccupied(array));
  return {probe, false};
}

TypeArguments::Cache::KeyLocation TypeArguments::Cache::AddEntry(
    intptr_t entry,
    const TypeArguments& instantiator_tav,
    const TypeArguments& function_tav,
    const TypeArguments& instantiated_tav) const {
  // We don't do mutating operations in tests without a TypeArguments object.
  ASSERT(cache_container_ != nullptr);
#if defined(DEBUG)
  auto loc = FindKeyOrUnused(instantiator_tav, function_tav);
  ASSERT_EQUAL(loc.entry, entry);
  ASSERT(!loc.present);
#endif
  // Double-check we got the expected entry index when adding to a linear array.
  ASSERT(!IsLinear() || entry == NumOccupied());
  const intptr_t new_occupied = NumOccupied() + 1;
  const bool storage_changed = EnsureCapacity(new_occupied);
  // Note that this call to IsLinear() may return a different result than the
  // earlier, since EnsureCapacity() may have swapped to hash-based storage.
  if (storage_changed && !IsLinear()) {
    // The capacity of the array has changed, and the capacity is used when
    // probing further into the array due to collisions. Thus, we need to redo
    // the entry index calculation.
    auto loc = FindKeyOrUnused(instantiator_tav, function_tav);
    ASSERT(!loc.present);
    entry = loc.entry;
  }

  // Go ahead and increment the number of occupied entries prior to adding the
  // entry. Use a store-release barrier in case of concurrent readers.
  const intptr_t metadata = RawSmiValue(Smi::RawCast(data_.At(kMetadataIndex)));
  smi_handle_ = Smi::New(NumOccupiedBits::update(new_occupied, metadata));
  data_.SetAtRelease(kMetadataIndex, smi_handle_);

  InstantiationsCacheTable table(data_);
  const auto& tuple = table.At(entry);
  // The parts of the tuple that aren't used for sentinel checking are only
  // retrieved if the entry is occupied. Entries in the cache are never deleted,
  // so once the entry is marked as occupied, the contents of that entry never
  // change. Thus, we don't need store-release barriers here.
  tuple.Set<kFunctionTypeArgsIndex>(function_tav);
  tuple.Set<kInstantiatedTypeArgsIndex>(instantiated_tav);
  // For the sentinel position, though, we do.
  static_assert(
      kSentinelIndex == kInstantiatorTypeArgsIndex,
      "the sentinel position is not protected with a store-release barrier");
  tuple.Set<kInstantiatorTypeArgsIndex, std::memory_order_release>(
      instantiator_tav);

  if (storage_changed) {
    // Only check for validity on growth, just to keep the overhead on DEBUG
    // builds down.
    DEBUG_ASSERT(IsValidStorageLocked(data_));
    // Update the container of the original cache to point to the new one.
    cache_container_->set_instantiations(data_);
  }

  return {entry, true};
}

SmiPtr TypeArguments::Cache::Sentinel() {
  return Smi::New(kSentinelValue);
}

bool TypeArguments::Cache::EnsureCapacity(intptr_t new_occupied) const {
  ASSERT(new_occupied > NumOccupied());
  // How many entries are in the current array (including unoccupied entries).
  const intptr_t current_capacity = NumEntries();

  // Early returns for cases where no growth is needed.
  const bool is_linear = IsLinear();
  if (is_linear) {
    // We need at least one unoccupied entry in addition to the occupied ones.
    if (current_capacity > new_occupied) return false;
  } else {
    if (LoadFactor(new_occupied, current_capacity) < kMaxLoadFactor) {
      return false;
    }
  }

  if (new_occupied <= kMaxLinearCacheEntries) {
    ASSERT(is_linear);
    // Not enough room for both the new entry and at least one unoccupied
    // entry, so grow the tuple capacity of the linear cache by about 50%,
    // ensuring that space for at least one new tuple is added, capping the
    // total number of occupied entries to the max allowed.
    const intptr_t new_capacity =
        Utils::Minimum(current_capacity + (current_capacity >> 1),
                       kMaxLinearCacheEntries) +
        1;
    const intptr_t cache_size = kHeaderSize + new_capacity * kEntrySize;
    ASSERT(cache_size <= kMaxLinearCacheSize);
    data_ = Array::Grow(data_, cache_size, Heap::kOld);
    ASSERT(!data_.IsNull());
    // No need to adjust the number of occupied entries or old entries, as they
    // are copied over by Array::Grow. Just mark any new entries as unoccupied.
    smi_handle_ = Sentinel();
    InstantiationsCacheTable table(data_);
    for (intptr_t i = current_capacity; i < new_capacity; i++) {
      const auto& tuple = table.At(i);
      tuple.Set<kSentinelIndex>(smi_handle_);
    }
    return true;
  }

  // Either we're converting a linear cache into a hash-based cache, or the
  // load factor of the hash-based cache has increased to the point where we
  // need to grow it.
  const intptr_t new_capacity =
      is_linear ? kNumInitialHashCacheEntries : 2 * current_capacity;
  // Because we use quadratic (actually triangle number) probing it is
  // important that the size is a power of two (otherwise we could fail to
  // find an empty slot).  This is described in Knuth's The Art of Computer
  // Programming Volume 2, Chapter 6.4, exercise 20 (solution in the
  // appendix, 2nd edition).
  ASSERT(Utils::IsPowerOfTwo(new_capacity));
  ASSERT(LoadFactor(new_occupied, new_capacity) < kMaxLoadFactor);
  const intptr_t new_size = kHeaderSize + new_capacity * kEntrySize;
  const auto& new_data =
      Array::Handle(zone_, Array::NewUninitialized(new_size, Heap::kOld));
  ASSERT(!new_data.IsNull());
  // First set up the metadata in new_data.
  const intptr_t metadata = RawSmiValue(Smi::RawCast(data_.At(kMetadataIndex)));
  smi_handle_ = Smi::New(EntryCountLog2Bits::update(
      Utils::ShiftForPowerOfTwo(new_capacity), metadata));
  new_data.SetAt(kMetadataIndex, smi_handle_);
  // Then mark all the entries in new_data as unoccupied.
  smi_handle_ = Sentinel();
  InstantiationsCacheTable to_table(new_data);
  for (const auto& tuple : to_table) {
    tuple.Set<kSentinelIndex>(smi_handle_);
  }
  // Finally, copy over the entries.
  auto& instantiator_tav = TypeArguments::Handle(zone_);
  auto& function_tav = TypeArguments::Handle(zone_);
  auto& result_tav = TypeArguments::Handle(zone_);
  const InstantiationsCacheTable from_table(data_);
  for (const auto& from_tuple : from_table) {
    // Skip unoccupied entries.
    if (from_tuple.Get<kSentinelIndex>() == Sentinel()) continue;
    instantiator_tav ^= from_tuple.Get<kInstantiatorTypeArgsIndex>();
    function_tav = from_tuple.Get<kFunctionTypeArgsIndex>();
    result_tav = from_tuple.Get<kInstantiatedTypeArgsIndex>();
    // Since new_data has a different total capacity, we can't use the old
    // entry indexes, but must recalculate them.
    auto loc = FindKeyOrUnused(new_data, instantiator_tav, function_tav);
    ASSERT(!loc.present);
    const auto& to_tuple = to_table.At(loc.entry);
    to_tuple.Set<kInstantiatorTypeArgsIndex>(instantiator_tav);
    to_tuple.Set<kFunctionTypeArgsIndex>(function_tav);
    to_tuple.Set<kInstantiatedTypeArgsIndex>(result_tav);
  }
  data_ = new_data.ptr();
  return true;
}

bool TypeArguments::HasInstantiations() const {
  return instantiations() != Cache::EmptyStorage().ptr();
}

ArrayPtr TypeArguments::instantiations() const {
  // We rely on the fact that any loads from the array are dependent loads and
  // avoid the load-acquire barrier here.
  return untag()->instantiations();
}

void TypeArguments::set_instantiations(const Array& value) const {
  // We have to ensure that initializing stores to the array are available
  // when releasing the pointer to the array pointer.
  // => We have to use store-release here.
  ASSERT(!value.IsNull());
  untag()->set_instantiations<std::memory_order_release>(value.ptr());
}

bool TypeArguments::HasCount(intptr_t count) const {
  if (IsNull()) {
    return true;
  }
  return Length() == count;
}

intptr_t TypeArguments::Length() const {
  if (IsNull()) {
    return 0;
  }
  return Smi::Value(untag()->length());
}

intptr_t TypeArguments::nullability() const {
  if (IsNull()) {
    return 0;
  }
  return Smi::Value(untag()->nullability());
}

AbstractTypePtr TypeArguments::TypeAt(intptr_t index) const {
  ASSERT(!IsNull());
  ASSERT((index >= 0) && (index < Length()));
  return untag()->element(index);
}

AbstractTypePtr TypeArguments::TypeAtNullSafe(intptr_t index) const {
  if (IsNull()) {
    // null vector represents infinite list of dynamics
    return Type::dynamic_type().ptr();
  }
  ASSERT((index >= 0) && (index < Length()));
  return TypeAt(index);
}

void TypeArguments::SetTypeAt(intptr_t index, const AbstractType& value) const {
  ASSERT(!IsCanonical());
  ASSERT((index >= 0) && (index < Length()));
  return untag()->set_element(index, value.ptr());
}

bool TypeArguments::IsSubvectorInstantiated(
    intptr_t from_index,
    intptr_t len,
    Genericity genericity,
    intptr_t num_free_fun_type_params) const {
  ASSERT(!IsNull());
  AbstractType& type = AbstractType::Handle();
  for (intptr_t i = 0; i < len; i++) {
    type = TypeAt(from_index + i);
    // If this type argument T is null, the type A containing T in its flattened
    // type argument vector V is recursive and is still being finalized.
    // T is the type argument of a super type of A. T is being instantiated
    // during finalization of V, which is also the instantiator. T depends
    // solely on the type parameters of A and will be replaced by a non-null
    // type before A is marked as finalized.
    if (!type.IsNull() &&
        !type.IsInstantiated(genericity, num_free_fun_type_params)) {
      return false;
    }
  }
  return true;
}

bool TypeArguments::IsUninstantiatedIdentity() const {
  AbstractType& type = AbstractType::Handle();
  const intptr_t num_types = Length();
  for (intptr_t i = 0; i < num_types; i++) {
    type = TypeAt(i);
    if (type.IsNull()) {
      return false;  // Still unfinalized, too early to tell.
    }
    if (!type.IsTypeParameter()) {
      return false;
    }
    const TypeParameter& type_param = TypeParameter::Cast(type);
    ASSERT(type_param.IsFinalized());
    if ((type_param.index() != i) || type_param.IsFunctionTypeParameter()) {
      return false;
    }
    // Instantiating nullable type parameters may change
    // nullability of a type, so type arguments vector containing such type
    // parameters cannot be substituted with instantiator type arguments.
    if (type_param.IsNullable()) {
      return false;
    }
  }
  return true;
  // Note that it is not necessary to verify at runtime that the instantiator
  // type vector is long enough, since this uninstantiated vector contains as
  // many different type parameters as it is long.
}

// Return true if this uninstantiated type argument vector, once instantiated
// at runtime, is a prefix of the type argument vector of its instantiator.
// A runtime check may be required, as indicated by with_runtime_check.
bool TypeArguments::CanShareInstantiatorTypeArguments(
    const Class& instantiator_class,
    bool* with_runtime_check) const {
  ASSERT(!IsInstantiated());
  if (with_runtime_check != nullptr) {
    *with_runtime_check = false;
  }
  const intptr_t num_type_args = Length();
  const intptr_t num_instantiator_type_args =
      instantiator_class.NumTypeArguments();
  if (num_type_args > num_instantiator_type_args) {
    // This vector cannot be a prefix of a shorter vector.
    return false;
  }
  const intptr_t num_instantiator_type_params =
      instantiator_class.NumTypeParameters();
  const intptr_t first_type_param_offset =
      num_instantiator_type_args - num_instantiator_type_params;
  // At compile time, the type argument vector of the instantiator consists of
  // the type argument vector of its super type, which may refer to the type
  // parameters of the instantiator class, followed by (or overlapping partially
  // or fully with) the type parameters of the instantiator class in declaration
  // order.
  // In other words, the only variables are the type parameters of the
  // instantiator class.
  // This uninstantiated type argument vector is also expressed in terms of the
  // type parameters of the instantiator class. Therefore, in order to be a
  // prefix once instantiated at runtime, every one of its type argument must be
  // equal to the type argument of the instantiator vector at the same index.

  // As a first requirement, the last num_instantiator_type_params type
  // arguments of this type argument vector must refer to the corresponding type
  // parameters of the instantiator class.
  AbstractType& type_arg = AbstractType::Handle();
  for (intptr_t i = first_type_param_offset; i < num_type_args; i++) {
    type_arg = TypeAt(i);
    if (!type_arg.IsTypeParameter()) {
      return false;
    }
    const TypeParameter& type_param = TypeParameter::Cast(type_arg);
    ASSERT(type_param.IsFinalized());
    if ((type_param.index() != i) || type_param.IsFunctionTypeParameter()) {
      return false;
    }
    // Instantiating nullable type parameters may change nullability
    // of a type, so type arguments vector containing such type parameters
    // cannot be substituted with instantiator type arguments, unless we check
    // at runtime the nullability of the first 1 or 2 type arguments of the
    // instantiator.
    // Note that the presence of non-overlapping super type arguments (i.e.
    // first_type_param_offset > 0) will prevent this optimization.
    if (type_param.IsNullable()) {
      if (with_runtime_check == nullptr || i >= kNullabilityMaxTypes) {
        return false;
      }
      *with_runtime_check = true;
    }
  }
  // As a second requirement, the type arguments corresponding to the super type
  // must be identical. Overlapping ones have already been checked starting at
  // first_type_param_offset.
  if (first_type_param_offset == 0) {
    return true;
  }
  Type& super_type = Type::Handle(instantiator_class.super_type());
  const TypeArguments& super_type_args =
      TypeArguments::Handle(super_type.GetInstanceTypeArguments(
          Thread::Current(), /*canonicalize=*/false));
  if (super_type_args.IsNull()) {
    ASSERT(!IsUninstantiatedIdentity());
    return false;
  }
  AbstractType& super_type_arg = AbstractType::Handle();
  for (intptr_t i = 0; (i < first_type_param_offset) && (i < num_type_args);
       i++) {
    type_arg = TypeAt(i);
    super_type_arg = super_type_args.TypeAt(i);
    if (!type_arg.Equals(super_type_arg)) {
      ASSERT(!IsUninstantiatedIdentity());
      return false;
    }
  }
  return true;
}

// Return true if this uninstantiated type argument vector, once instantiated
// at runtime, is a prefix of the enclosing function type arguments.
// A runtime check may be required, as indicated by with_runtime_check.
bool TypeArguments::CanShareFunctionTypeArguments(
    const Function& function,
    bool* with_runtime_check) const {
  ASSERT(!IsInstantiated());
  if (with_runtime_check != nullptr) {
    *with_runtime_check = false;
  }
  const intptr_t num_type_args = Length();
  const intptr_t num_parent_type_args = function.NumParentTypeArguments();
  const intptr_t num_function_type_params = function.NumTypeParameters();
  const intptr_t num_function_type_args =
      num_parent_type_args + num_function_type_params;
  if (num_type_args > num_function_type_args) {
    // This vector cannot be a prefix of a shorter vector.
    return false;
  }
  AbstractType& type_arg = AbstractType::Handle();
  for (intptr_t i = 0; i < num_type_args; i++) {
    type_arg = TypeAt(i);
    if (!type_arg.IsTypeParameter()) {
      return false;
    }
    const TypeParameter& type_param = TypeParameter::Cast(type_arg);
    ASSERT(type_param.IsFinalized());
    if ((type_param.index() != i) || !type_param.IsFunctionTypeParameter()) {
      return false;
    }
    // Instantiating nullable type parameters may change nullability
    // of a type, so type arguments vector containing such type parameters
    // cannot be substituted with the enclosing function type arguments, unless
    // we check at runtime the nullability of the first 1 or 2 type arguments of
    // the enclosing function type arguments.
    if (type_param.IsNullable()) {
      if (with_runtime_check == nullptr || i >= kNullabilityMaxTypes) {
        return false;
      }
      *with_runtime_check = true;
    }
  }
  return true;
}

TypeArgumentsPtr TypeArguments::TruncatedTo(intptr_t length) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const TypeArguments& result =
      TypeArguments::Handle(zone, TypeArguments::New(length));
  AbstractType& type = AbstractType::Handle(zone);
  for (intptr_t i = 0; i < length; i++) {
    type = TypeAt(i);
    result.SetTypeAt(i, type);
  }
  return result.Canonicalize(thread);
}

bool TypeArguments::IsFinalized() const {
  ASSERT(!IsNull());
  AbstractType& type = AbstractType::Handle();
  const intptr_t num_types = Length();
  for (intptr_t i = 0; i < num_types; i++) {
    type = TypeAt(i);
    if (!type.IsFinalized()) {
      return false;
    }
  }
  return true;
}

TypeArgumentsPtr TypeArguments::InstantiateFrom(
    const TypeArguments& instantiator_type_arguments,
    const TypeArguments& function_type_arguments,
    intptr_t num_free_fun_type_params,
    Heap::Space space,
    FunctionTypeMapping* function_type_mapping,
    intptr_t num_parent_type_args_adjustment) const {
  ASSERT(!IsInstantiated());
  if ((instantiator_type_arguments.IsNull() ||
       instantiator_type_arguments.Length() == Length()) &&
      IsUninstantiatedIdentity()) {
    return instantiator_type_arguments.ptr();
  }
  const intptr_t num_types = Length();
  TypeArguments& instantiated_array =
      TypeArguments::Handle(TypeArguments::New(num_types, space));
  AbstractType& type = AbstractType::Handle();
  for (intptr_t i = 0; i < num_types; i++) {
    type = TypeAt(i);
    // If this type argument T is null, the type A containing T in its flattened
    // type argument vector V is recursive and is still being finalized.
    // T is the type argument of a super type of A. T is being instantiated
    // during finalization of V, which is also the instantiator. T depends
    // solely on the type parameters of A and will be replaced by a non-null
    // type before A is marked as finalized.
    if (!type.IsNull() && !type.IsInstantiated()) {
      type = type.InstantiateFrom(
          instantiator_type_arguments, function_type_arguments,
          num_free_fun_type_params, space, function_type_mapping,
          num_parent_type_args_adjustment);
      // A returned null type indicates a failed instantiation in dead code that
      // must be propagated up to the caller, the optimizing compiler.
      if (type.IsNull()) {
        return Object::empty_type_arguments().ptr();
      }
    }
    instantiated_array.SetTypeAt(i, type);
  }
  return instantiated_array.ptr();
}

TypeArgumentsPtr TypeArguments::UpdateFunctionTypes(
    intptr_t num_parent_type_args_adjustment,
    intptr_t num_free_fun_type_params,
    Heap::Space space,
    FunctionTypeMapping* function_type_mapping) const {
  Zone* zone = Thread::Current()->zone();
  TypeArguments* updated_args = nullptr;
  AbstractType& type = AbstractType::Handle(zone);
  AbstractType& updated = AbstractType::Handle(zone);
  for (intptr_t i = 0, n = Length(); i < n; ++i) {
    type = TypeAt(i);
    updated = type.UpdateFunctionTypes(num_parent_type_args_adjustment,
                                       num_free_fun_type_params, space,
                                       function_type_mapping);
    if (type.ptr() != updated.ptr()) {
      if (updated_args == nullptr) {
        updated_args =
            &TypeArguments::Handle(zone, TypeArguments::New(n, space));
        for (intptr_t j = 0; j < i; ++j) {
          type = TypeAt(j);
          updated_args->SetTypeAt(j, type);
        }
      }
    }
    if (updated_args != nullptr) {
      updated_args->SetTypeAt(i, updated);
    }
  }
  return (updated_args != nullptr) ? updated_args->ptr() : ptr();
}

#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
// A local flag used only in object_test.cc that, when true, causes a failure
// when a cache entry for the given instantiator and function type arguments
// already exists. Used to check that the InstantiateTypeArguments stub found
// the cache entry instead of calling the runtime.
bool TESTING_runtime_fail_on_existing_cache_entry = false;
#endif

TypeArgumentsPtr TypeArguments::InstantiateAndCanonicalizeFrom(
    const TypeArguments& instantiator_type_arguments,
    const TypeArguments& function_type_arguments) const {
  auto thread = Thread::Current();
  auto zone = thread->zone();
  SafepointMutexLocker ml(
      thread->isolate_group()->type_arguments_canonicalization_mutex());

  ASSERT(!IsInstantiated());
  ASSERT(instantiator_type_arguments.IsNull() ||
         instantiator_type_arguments.IsCanonical());
  ASSERT(function_type_arguments.IsNull() ||
         function_type_arguments.IsCanonical());
  // Lookup instantiators and if found, return instantiated result.
  Cache cache(zone, *this);
  auto const loc = cache.FindKeyOrUnused(instantiator_type_arguments,
                                         function_type_arguments);
  if (loc.present) {
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
    if (TESTING_runtime_fail_on_existing_cache_entry) {
      TextBuffer buffer(1024);
      buffer.Printf("for\n");
      buffer.Printf("  * uninstantiated type arguments %s\n", ToCString());
      buffer.Printf("  * instantiation type arguments: %s (hash: %" Pu ")\n",
                    instantiator_type_arguments.ToCString(),
                    instantiator_type_arguments.Hash());
      buffer.Printf("  * function type arguments: %s (hash: %" Pu ")\n",
                    function_type_arguments.ToCString(),
                    function_type_arguments.Hash());
      buffer.Printf("  * number of occupied entries in cache: %" Pd "\n",
                    cache.NumOccupied());
      buffer.Printf("  * number of total entries in cache: %" Pd "\n",
                    cache.NumEntries());
      buffer.Printf("expected to find entry %" Pd
                    " of cache in stub, but reached runtime",
                    loc.entry);
      FATAL("%s", buffer.buffer());
    }
#endif
    return cache.Retrieve(loc.entry);
  }
  // Cache lookup failed. Instantiate the type arguments.
  TypeArguments& result = TypeArguments::Handle(zone);
  result = InstantiateFrom(instantiator_type_arguments, function_type_arguments,
                           kAllFree, Heap::kOld);
  // Canonicalize type arguments.
  result = result.Canonicalize(thread);
  // InstantiateAndCanonicalizeFrom is not reentrant. It cannot have been called
  // indirectly, so the prior_instantiations array cannot have grown.
  ASSERT(cache.data_.ptr() == instantiations());
  cache.AddEntry(loc.entry, instantiator_type_arguments,
                 function_type_arguments, result);
  return result.ptr();
}

TypeArgumentsPtr TypeArguments::New(intptr_t len, Heap::Space space) {
  if (len < 0 || len > kMaxElements) {
    // This should be caught before we reach here.
    FATAL("Fatal error in TypeArguments::New: invalid len %" Pd "\n", len);
  }
  TypeArguments& result = TypeArguments::Handle();
  {
    auto raw = Object::Allocate<TypeArguments>(space, len);
    NoSafepointScope no_safepoint;
    result = raw;
    // Length must be set before we start storing into the array.
    result.SetLength(len);
    result.SetHash(0);
    result.set_nullability(0);
  }
  // The array used as storage for an empty linear cache should be initialized.
  ASSERT(Cache::EmptyStorage().ptr() != Array::null());
  result.set_instantiations(Cache::EmptyStorage());
  return result.ptr();
}

void TypeArguments::SetLength(intptr_t value) const {
  ASSERT(!IsCanonical());
  // This is only safe because we create a new Smi, which does not cause
  // heap allocation.
  untag()->set_length(Smi::New(value));
}

TypeArgumentsPtr TypeArguments::Canonicalize(Thread* thread) const {
  if (IsNull() || IsCanonical()) {
    ASSERT(IsOld());
    return this->ptr();
  }
  const intptr_t num_types = Length();
  if (num_types == 0) {
    return TypeArguments::empty_type_arguments().ptr();
  } else if (IsRaw(0, num_types)) {
    return TypeArguments::null();
  }
  Zone* zone = thread->zone();
  auto isolate_group = thread->isolate_group();
  ObjectStore* object_store = isolate_group->object_store();
  TypeArguments& result = TypeArguments::Handle(zone);
  {
    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
    CanonicalTypeArgumentsSet table(zone,
                                    object_store->canonical_type_arguments());
    result ^= table.GetOrNull(CanonicalTypeArgumentsKey(*this));
    object_store->set_canonical_type_arguments(table.Release());
  }
  if (result.IsNull()) {
    // Canonicalize each type argument.
    AbstractType& type_arg = AbstractType::Handle(zone);
    GrowableHandlePtrArray<const AbstractType> canonicalized_types(zone,
                                                                   num_types);
    for (intptr_t i = 0; i < num_types; i++) {
      type_arg = TypeAt(i);
      type_arg = type_arg.Canonicalize(thread);
      canonicalized_types.Add(type_arg);
    }
    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
    CanonicalTypeArgumentsSet table(zone,
                                    object_store->canonical_type_arguments());
    // Since we canonicalized some type arguments above we need to lookup
    // in the table again to make sure we don't already have an equivalent
    // canonical entry.
    result ^= table.GetOrNull(CanonicalTypeArgumentsKey(*this));
    if (result.IsNull()) {
      for (intptr_t i = 0; i < num_types; i++) {
        SetTypeAt(i, canonicalized_types.At(i));
      }
      // Make sure we have an old space object and add it to the table.
      if (this->IsNew()) {
        result ^= Object::Clone(*this, Heap::kOld);
      } else {
        result = this->ptr();
      }
      ASSERT(result.IsOld());
      result.ComputeNullability();
      result.SetCanonical();  // Mark object as being canonical.
      // Now add this TypeArgument into the canonical list of type arguments.
      bool present = table.Insert(result);
      ASSERT(!present);
    }
    object_store->set_canonical_type_arguments(table.Release());
  }
  ASSERT(result.Equals(*this));
  ASSERT(!result.IsNull());
  ASSERT(result.IsTypeArguments());
  ASSERT(result.IsCanonical());
  return result.ptr();
}

TypeArgumentsPtr TypeArguments::FromInstanceTypeArguments(
    Thread* thread,
    const Class& cls) const {
  if (IsNull()) {
    return ptr();
  }
  const intptr_t num_type_arguments = cls.NumTypeArguments();
  const intptr_t num_type_parameters = cls.NumTypeParameters(thread);
  ASSERT(Length() >= num_type_arguments);
  if (Length() == num_type_parameters) {
    return ptr();
  }
  if (num_type_parameters == 0) {
    return TypeArguments::null();
  }
  Zone* zone = thread->zone();
  const auto& args =
      TypeArguments::Handle(zone, TypeArguments::New(num_type_parameters));
  const intptr_t offset = num_type_arguments - num_type_parameters;
  auto& type = AbstractType::Handle(zone);
  for (intptr_t i = 0; i < num_type_parameters; ++i) {
    type = TypeAt(offset + i);
    args.SetTypeAt(i, type);
  }
  return args.ptr();
}

TypeArgumentsPtr TypeArguments::ToInstantiatorTypeArguments(
    Thread* thread,
    const Class& cls) const {
  if (IsNull()) {
    return ptr();
  }
  const intptr_t num_type_arguments = cls.NumTypeArguments();
  const intptr_t num_type_parameters = cls.NumTypeParameters(thread);
  ASSERT(Length() == num_type_parameters);
  if (num_type_arguments == num_type_parameters) {
    return ptr();
  }
  Zone* zone = thread->zone();
  const auto& args =
      TypeArguments::Handle(zone, TypeArguments::New(num_type_arguments));
  const intptr_t offset = num_type_arguments - num_type_parameters;
  auto& type = AbstractType::Handle(zone);
  for (intptr_t i = 0; i < num_type_parameters; ++i) {
    type = TypeAt(i);
    args.SetTypeAt(offset + i, type);
  }
  return args.ptr();
}

void TypeArguments::EnumerateURIs(URIs* uris) const {
  if (IsNull()) {
    return;
  }
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  AbstractType& type = AbstractType::Handle(zone);
  const intptr_t num_types = Length();
  for (intptr_t i = 0; i < num_types; i++) {
    type = TypeAt(i);
    type.EnumerateURIs(uris);
  }
}

const char* TypeArguments::ToCString() const {
  if (IsNull()) {
    return "TypeArguments: null";  // Optimizing the frequent case.
  }
  ZoneTextBuffer buffer(Thread::Current()->zone());
  PrintTo(&buffer);
  return buffer.buffer();
}

const char* PatchClass::ToCString() const {
  const Class& cls = Class::Handle(wrapped_class());
  const char* cls_name = cls.ToCString();
  return OS::SCreate(Thread::Current()->zone(), "PatchClass for %s", cls_name);
}

PatchClassPtr PatchClass::New(const Class& wrapped_class,
                              const KernelProgramInfo& info,
                              const Script& script) {
  const PatchClass& result = PatchClass::Handle(PatchClass::New());
  result.set_wrapped_class(wrapped_class);
  NOT_IN_PRECOMPILED_RUNTIME(
      result.untag()->set_kernel_program_info(info.ptr()));
  result.set_script(script);
  result.set_kernel_library_index(-1);
  return result.ptr();
}

PatchClassPtr PatchClass::New() {
  ASSERT(Object::patch_class_class() != Class::null());
  return Object::Allocate<PatchClass>(Heap::kOld);
}

void PatchClass::set_wrapped_class(const Class& value) const {
  untag()->set_wrapped_class(value.ptr());
}

#if !defined(DART_PRECOMPILED_RUNTIME)
void PatchClass::set_kernel_program_info(const KernelProgramInfo& info) const {
  untag()->set_kernel_program_info(info.ptr());
}
#endif

void PatchClass::set_script(const Script& value) const {
  untag()->set_script(value.ptr());
}

uword Function::Hash() const {
  uint32_t hash = String::HashRawSymbol(name());
  if (IsNonImplicitClosureFunction()) {
    hash = CombineHashes(hash, token_pos().Hash());
  }
  if (Owner()->IsClass()) {
    hash = CombineHashes(hash, Class::Hash(Class::RawCast(Owner())));
  }
  return hash;
}

bool Function::HasBreakpoint() const {
#if defined(PRODUCT)
  return false;
#else
  auto thread = Thread::Current();
  return thread->isolate_group()->debugger()->HasBreakpoint(thread, *this);
#endif
}

void Function::InstallOptimizedCode(const Code& code) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  // We may not have previous code if FLAG_precompile is set.
  // Hot-reload may have already disabled the current code.
  if (HasCode() && !Code::Handle(CurrentCode()).IsDisabled()) {
    Code::Handle(CurrentCode()).DisableDartCode();
  }
  AttachCode(code);
}

void Function::SetInstructions(const Code& value) const {
  // Ensure that nobody is executing this function when we install it.
  if (untag()->code() != Code::null() && HasCode()) {
    GcSafepointOperationScope safepoint(Thread::Current());
    SetInstructionsSafe(value);
  } else {
    ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
    SetInstructionsSafe(value);
  }
}

void Function::SetInstructionsSafe(const Code& value) const {
  untag()->set_code<std::memory_order_release>(value.ptr());
  StoreNonPointer(&untag()->entry_point_, value.EntryPoint());
  StoreNonPointer(&untag()->unchecked_entry_point_,
                  value.UncheckedEntryPoint());
}

void Function::AttachCode(const Code& value) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  // Finish setting up code before activating it.
  value.set_owner(*this);
  SetInstructions(value);
  ASSERT(Function::Handle(value.function()).IsNull() ||
         (value.function() == this->ptr()));
}

bool Function::HasCode() const {
  NoSafepointScope no_safepoint;
  ASSERT(untag()->code() != Code::null());
  return untag()->code() != StubCode::LazyCompile().ptr();
}

#if defined(DART_DYNAMIC_MODULES)

void Function::AttachBytecode(const Bytecode& value) const {
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  ASSERT(!value.IsNull());
  // Finish setting up code before activating it.
  if (!value.InVMIsolateHeap()) {
    value.set_function(*this);
  }
  ASSERT(untag()->ic_data_array_or_bytecode() == Object::null());
  untag()->set_ic_data_array_or_bytecode(value.ptr());

  // Set the code entry_point to InterpretCall stub.
  SetInstructions(StubCode::InterpretCall());
}

void Function::ClearBytecode() const {
  ASSERT(HasBytecode());
  untag()->set_ic_data_array_or_bytecode(Object::null());
  ClearCode();
}

#endif  // defined(DART_DYNAMIC_MODULES)

bool Function::HasCode(FunctionPtr function) {
  NoSafepointScope no_safepoint;
  ASSERT(function->untag()->code() != Code::null());
  return function->untag()->code() != StubCode::LazyCompile().ptr();
}

void Function::ClearCode() const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  untag()->set_unoptimized_code(Code::null());
  SetInstructions(StubCode::LazyCompile());
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

void Function::ClearCodeSafe() const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  untag()->set_unoptimized_code(Code::null());

  SetInstructionsSafe(StubCode::LazyCompile());
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

void Function::EnsureHasCompiledUnoptimizedCode() const {
  ASSERT(!ForceOptimize());
  Thread* thread = Thread::Current();
  ASSERT(thread->IsDartMutatorThread());
  DEBUG_ASSERT(thread->TopErrorHandlerIsExitFrame());
  Zone* zone = thread->zone();

  const Error& error =
      Error::Handle(zone, EnsureHasCompiledUnoptimizedCodeNoThrow());
  if (!error.IsNull()) {
    Exceptions::PropagateError(error);
  }
}

ErrorPtr Function::EnsureHasCompiledUnoptimizedCodeNoThrow() const {
  ASSERT(!ForceOptimize());
  Thread* thread = Thread::Current();
  ASSERT(thread->IsDartMutatorThread());

  return Compiler::EnsureUnoptimizedCode(thread, *this);
}

void Function::SwitchToUnoptimizedCode() const {
  ASSERT(HasOptimizedCode());
  ASSERT(!ForceOptimize());
  Thread* thread = Thread::Current();
  DEBUG_ASSERT(
      thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
  Zone* zone = thread->zone();
  // TODO(35224): DEBUG_ASSERT(thread->TopErrorHandlerIsExitFrame());
  const Code& current_code = Code::Handle(zone, CurrentCode());

  if (FLAG_trace_deoptimization_verbose) {
    THR_Print("Disabling optimized code: '%s' entry: %#" Px "\n",
              ToFullyQualifiedCString(), current_code.EntryPoint());
  }
  current_code.DisableDartCode();
  const Error& error =
      Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, *this));
  if (!error.IsNull()) {
    Exceptions::PropagateError(error);
  }
  const Code& unopt_code = Code::Handle(zone, unoptimized_code());
  unopt_code.Enable();
  AttachCode(unopt_code);
}

void Function::SwitchToLazyCompiledUnoptimizedCode() const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  if (!HasOptimizedCode()) {
    return;
  }

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

  const Code& current_code = Code::Handle(zone, CurrentCode());
  TIR_Print("Disabling optimized code for %s\n", ToCString());
  current_code.DisableDartCode();

  const Code& unopt_code = Code::Handle(zone, unoptimized_code());
  if (unopt_code.IsNull()) {
    // Set the lazy compile stub code.
    TIR_Print("Switched to lazy compile stub for %s\n", ToCString());
    SetInstructions(StubCode::LazyCompile());
    return;
  }

  TIR_Print("Switched to unoptimized code for %s\n", ToCString());

  AttachCode(unopt_code);
  unopt_code.Enable();
#endif
}

void Function::set_unoptimized_code(const Code& value) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  DEBUG_ASSERT(IsMutatorOrAtDeoptSafepoint());
  ASSERT(value.IsNull() || !value.is_optimized());
  untag()->set_unoptimized_code(value.ptr());
#endif
}

ContextScopePtr Function::context_scope() const {
  if (IsClosureFunction()) {
    const Object& obj = Object::Handle(untag()->data());
    ASSERT(!obj.IsNull());
    return ClosureData::Cast(obj).context_scope();
  }
  return ContextScope::null();
}

void Function::set_context_scope(const ContextScope& value) const {
  if (IsClosureFunction()) {
    const Object& obj = Object::Handle(untag()->data());
    ASSERT(!obj.IsNull());
    ClosureData::Cast(obj).set_context_scope(value);
    return;
  }
  UNREACHABLE();
}

Function::AwaiterLink Function::awaiter_link() const {
  if (IsClosureFunction()) {
    const Object& obj = Object::Handle(untag()->data());
    ASSERT(!obj.IsNull());
    return ClosureData::Cast(obj).awaiter_link();
  }
  UNREACHABLE();
  return {};
}

void Function::set_awaiter_link(Function::AwaiterLink link) const {
  if (IsClosureFunction()) {
    const Object& obj = Object::Handle(untag()->data());
    ASSERT(!obj.IsNull());
    ClosureData::Cast(obj).set_awaiter_link(link);
    return;
  }
  UNREACHABLE();
}

ClosurePtr Function::implicit_static_closure() const {
  if (IsImplicitStaticClosureFunction()) {
    const Object& obj = Object::Handle(untag()->data());
    ASSERT(!obj.IsNull());
    return ClosureData::Cast(obj).implicit_static_closure();
  }
  return Closure::null();
}

void Function::set_implicit_static_closure(const Closure& closure) const {
  if (IsImplicitStaticClosureFunction()) {
    const Object& obj = Object::Handle(untag()->data());
    ASSERT(!obj.IsNull());
    ClosureData::Cast(obj).set_implicit_static_closure(closure);
    return;
  }
  UNREACHABLE();
}

ScriptPtr Function::eval_script() const {
  const Object& obj = Object::Handle(untag()->data());
  if (obj.IsScript()) {
    return Script::Cast(obj).ptr();
  }
  return Script::null();
}

void Function::set_eval_script(const Script& script) const {
  ASSERT(token_pos() == TokenPosition::kMinSource);
  ASSERT(untag()->data() == Object::null());
  set_data(script);
}

FunctionPtr Function::extracted_method_closure() const {
  ASSERT(kind() == UntaggedFunction::kMethodExtractor);
  const Object& obj = Object::Handle(untag()->data());
  ASSERT(obj.IsFunction());
  return Function::Cast(obj).ptr();
}

void Function::set_extracted_method_closure(const Function& value) const {
  ASSERT(kind() == UntaggedFunction::kMethodExtractor);
  ASSERT(untag()->data() == Object::null());
  set_data(value);
}

ArrayPtr Function::saved_args_desc() const {
  if (kind() == UntaggedFunction::kDynamicInvocationForwarder) {
    return Array::null();
  }
  ASSERT(kind() == UntaggedFunction::kNoSuchMethodDispatcher ||
         kind() == UntaggedFunction::kInvokeFieldDispatcher);
  return Array::RawCast(untag()->data());
}

void Function::set_saved_args_desc(const Array& value) const {
  ASSERT(kind() == UntaggedFunction::kNoSuchMethodDispatcher ||
         kind() == UntaggedFunction::kInvokeFieldDispatcher);
  ASSERT(untag()->data() == Object::null());
  set_data(value);
}

FieldPtr Function::accessor_field() const {
  ASSERT(kind() == UntaggedFunction::kImplicitGetter ||
         kind() == UntaggedFunction::kImplicitSetter ||
         kind() == UntaggedFunction::kImplicitStaticGetter ||
         kind() == UntaggedFunction::kFieldInitializer);
  return Field::RawCast(untag()->data());
}

void Function::set_accessor_field(const Field& value) const {
  ASSERT(kind() == UntaggedFunction::kImplicitGetter ||
         kind() == UntaggedFunction::kImplicitSetter ||
         kind() == UntaggedFunction::kImplicitStaticGetter ||
         kind() == UntaggedFunction::kFieldInitializer);
  // Top level classes may be finalized multiple times.
  ASSERT(untag()->data() == Object::null() || untag()->data() == value.ptr());
  set_data(value);
}

FunctionPtr Function::parent_function() const {
  if (!IsClosureFunction()) return Function::null();
  Object& obj = Object::Handle(untag()->data());
  ASSERT(!obj.IsNull());
  return ClosureData::Cast(obj).parent_function();
}

void Function::set_parent_function(const Function& value) const {
  ASSERT(IsClosureFunction());
  const Object& obj = Object::Handle(untag()->data());
  ASSERT(!obj.IsNull());
  ClosureData::Cast(obj).set_parent_function(value);
}

TypeArgumentsPtr Function::DefaultTypeArguments(Zone* zone) const {
  if (type_parameters() == TypeParameters::null()) {
    return Object::empty_type_arguments().ptr();
  }
  return TypeParameters::Handle(zone, type_parameters()).defaults();
}

InstantiationMode Function::default_type_arguments_instantiation_mode() const {
  if (!IsClosureFunction()) {
    UNREACHABLE();
  }
  return ClosureData::DefaultTypeArgumentsInstantiationMode(
      ClosureData::RawCast(data()));
}

void Function::set_default_type_arguments_instantiation_mode(
    InstantiationMode value) const {
  if (!IsClosureFunction()) {
    UNREACHABLE();
  }
  const auto& closure_data = ClosureData::Handle(ClosureData::RawCast(data()));
  ASSERT(!closure_data.IsNull());
  closure_data.set_default_type_arguments_instantiation_mode(value);
}

// Enclosing outermost function of this local function.
FunctionPtr Function::GetOutermostFunction() const {
  FunctionPtr parent = parent_function();
  if (parent == Object::null()) {
    return ptr();
  }
  Function& function = Function::Handle();
  do {
    function = parent;
    parent = function.parent_function();
  } while (parent != Object::null());
  return function.ptr();
}

FunctionPtr Function::implicit_closure_function() const {
  if (IsClosureFunction() || IsDispatcherOrImplicitAccessor() ||
      IsFieldInitializer() || IsFfiCallbackTrampoline() ||
      IsMethodExtractor()) {
    return Function::null();
  }
  const Object& obj = Object::Handle(data());
  ASSERT(obj.IsNull() || obj.IsScript() || obj.IsFunction() || obj.IsArray());
  if (obj.IsNull() || obj.IsScript()) {
    return Function::null();
  }
  if (obj.IsFunction()) {
    return Function::Cast(obj).ptr();
  }
  ASSERT(is_native());
  ASSERT(obj.IsArray());
  const Object& res = Object::Handle(Array::Cast(obj).AtAcquire(1));
  return res.IsNull() ? Function::null() : Function::Cast(res).ptr();
}

void Function::set_implicit_closure_function(const Function& value) const {
  DEBUG_ASSERT(
      IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  ASSERT(!IsClosureFunction());
  const Object& old_data = Object::Handle(data());
  if (is_old_native()) {
    ASSERT(old_data.IsArray());
    const auto& pair = Array::Cast(old_data);
    ASSERT(pair.AtAcquire(NativeFunctionData::kTearOff) == Object::null() ||
           value.IsNull());
    pair.SetAtRelease(NativeFunctionData::kTearOff, value);
  } else {
    ASSERT(old_data.IsNull() || value.IsNull());
    set_data(value);
  }
}

void Function::SetFfiCSignature(const FunctionType& sig) const {
  ASSERT(IsFfiCallbackTrampoline());
  const Object& obj = Object::Handle(data());
  ASSERT(!obj.IsNull());
  FfiTrampolineData::Cast(obj).set_c_signature(sig);
}

FunctionTypePtr Function::FfiCSignature() const {
  auto* const zone = Thread::Current()->zone();
  if (IsFfiCallbackTrampoline()) {
    const Object& obj = Object::Handle(zone, data());
    ASSERT(!obj.IsNull());
    return FfiTrampolineData::Cast(obj).c_signature();
  }
  auto& pragma_value = Instance::Handle(zone);
  if (is_ffi_native()) {
    pragma_value = GetNativeAnnotation();
  } else if (IsFfiCallClosure()) {
    pragma_value = GetFfiCallClosurePragmaValue();
  } else {
    UNREACHABLE();
  }
  const auto& type_args =
      TypeArguments::Handle(zone, pragma_value.GetTypeArguments());
  ASSERT(type_args.Length() == 1);
  const auto& native_type =
      FunctionType::Cast(AbstractType::ZoneHandle(zone, type_args.TypeAt(0)));
  return native_type.ptr();
}

bool Function::FfiCSignatureContainsHandles() const {
  const FunctionType& c_signature = FunctionType::Handle(FfiCSignature());
  return c_signature.ContainsHandles();
}

bool FunctionType::ContainsHandles() const {
  const intptr_t num_params = num_fixed_parameters();
  for (intptr_t i = 0; i < num_params; i++) {
    const bool is_handle =
        AbstractType::Handle(ParameterTypeAt(i)).type_class_id() ==
        kFfiHandleCid;
    if (is_handle) {
      return true;
    }
  }
  return AbstractType::Handle(result_type()).type_class_id() == kFfiHandleCid;
}

// Keep consistent with BaseMarshaller::IsCompound.
bool Function::FfiCSignatureReturnsStruct() const {
  ASSERT(IsFfiCallbackTrampoline());
  Zone* zone = Thread::Current()->zone();
  const auto& c_signature = FunctionType::Handle(zone, FfiCSignature());
  const auto& type = AbstractType::Handle(zone, c_signature.result_type());
  if (IsFfiTypeClassId(type.type_class_id())) {
    return false;
  }
  const auto& cls = Class::Handle(zone, type.type_class());
  const auto& superClass = Class::Handle(zone, cls.SuperClass());
  const bool is_abi_specific_int =
      String::Handle(zone, superClass.UserVisibleName())
          .Equals(Symbols::AbiSpecificInteger());
  if (is_abi_specific_int) {
    return false;
  }
#ifdef DEBUG
  const bool is_struct = String::Handle(zone, superClass.UserVisibleName())
                             .Equals(Symbols::Struct());
  const bool is_union = String::Handle(zone, superClass.UserVisibleName())
                            .Equals(Symbols::Union());
  ASSERT(is_struct || is_union);
#endif
  return true;
}

bool Function::FfiCSignatureReturnsHandle() const {
  ASSERT(IsFfiCallbackTrampoline());
  const auto& c_signature = FunctionType::Handle(FfiCSignature());
  const auto& type = AbstractType::Handle(c_signature.result_type());
  return type.type_class_id() == kFfiHandleCid;
}

int32_t Function::FfiCallbackId() const {
  ASSERT(IsFfiCallbackTrampoline());

  const auto& obj = Object::Handle(data());
  ASSERT(!obj.IsNull());
  const auto& trampoline_data = FfiTrampolineData::Cast(obj);

  ASSERT(trampoline_data.callback_id() != -1);

  return trampoline_data.callback_id();
}

void Function::AssignFfiCallbackId(int32_t callback_id) const {
  ASSERT(IsFfiCallbackTrampoline());

  const auto& obj = Object::Handle(data());
  ASSERT(!obj.IsNull());
  const auto& trampoline_data = FfiTrampolineData::Cast(obj);

  ASSERT(trampoline_data.callback_id() == -1);
  trampoline_data.set_callback_id(callback_id);
}

bool Function::FfiIsLeaf() const {
  Zone* zone = Thread::Current()->zone();
  auto& pragma_value = Instance::Handle(zone);
  if (is_ffi_native()) {
    pragma_value = GetNativeAnnotation();
  } else if (IsFfiCallClosure()) {
    pragma_value = GetFfiCallClosurePragmaValue();
  } else {
    UNREACHABLE();
  }
  const auto& pragma_value_class = Class::Handle(zone, pragma_value.clazz());
  const auto& is_leaf_field = Field::Handle(
      zone, pragma_value_class.LookupFieldAllowPrivate(Symbols::isLeaf()));
  ASSERT(!is_leaf_field.IsNull());
  return Bool::Handle(zone, Bool::RawCast(pragma_value.GetField(is_leaf_field)))
      .value();
}

FunctionPtr Function::FfiCallbackTarget() const {
  ASSERT(IsFfiCallbackTrampoline());
  const Object& obj = Object::Handle(data());
  ASSERT(!obj.IsNull());
  return FfiTrampolineData::Cast(obj).callback_target();
}

void Function::SetFfiCallbackTarget(const Function& target) const {
  ASSERT(IsFfiCallbackTrampoline());
  const Object& obj = Object::Handle(data());
  ASSERT(!obj.IsNull());
  FfiTrampolineData::Cast(obj).set_callback_target(target);
}

InstancePtr Function::FfiCallbackExceptionalReturn() const {
  ASSERT(IsFfiCallbackTrampoline());
  const Object& obj = Object::Handle(data());
  ASSERT(!obj.IsNull());
  return FfiTrampolineData::Cast(obj).callback_exceptional_return();
}

void Function::SetFfiCallbackExceptionalReturn(const Instance& value) const {
  ASSERT(IsFfiCallbackTrampoline());
  const Object& obj = Object::Handle(data());
  ASSERT(!obj.IsNull());
  FfiTrampolineData::Cast(obj).set_callback_exceptional_return(value);
}

FfiCallbackKind Function::GetFfiCallbackKind() const {
  ASSERT(IsFfiCallbackTrampoline());
  const Object& obj = Object::Handle(data());
  ASSERT(!obj.IsNull());
  return FfiTrampolineData::Cast(obj).ffi_function_kind();
}

void Function::SetFfiCallbackKind(FfiCallbackKind value) const {
  ASSERT(IsFfiCallbackTrampoline());
  const Object& obj = Object::Handle(data());
  ASSERT(!obj.IsNull());
  FfiTrampolineData::Cast(obj).set_ffi_function_kind(value);
}

const char* Function::KindToCString(UntaggedFunction::Kind kind) {
  return UntaggedFunction::KindToCString(kind);
}

FunctionPtr Function::ForwardingTarget() const {
  ASSERT(kind() == UntaggedFunction::kDynamicInvocationForwarder);
  return Function::RawCast(WeakSerializationReference::Unwrap(data()));
}

void Function::SetForwardingTarget(const Function& target) const {
  ASSERT(kind() == UntaggedFunction::kDynamicInvocationForwarder);
  set_data(target);
}

// This field is heavily overloaded:
//   kernel eval function:    Array[0] = Script
//                            Array[1] = KernelProgramInfo
//                            Array[2] = Kernel index of enclosing library
//   method extractor:        Function extracted closure function
//   implicit getter:         Field
//   implicit setter:         Field
//   impl. static final gttr: Field
//   field initializer:       Field
//   noSuchMethod dispatcher: Array arguments descriptor
//   invoke-field dispatcher: Array arguments descriptor
//   closure function:        ClosureData
//   irregexp function:       Array[0] = RegExp
//                            Array[1] = Smi string specialization cid
//   native function:         Array[0] = String native name
//                            Array[1] = Function implicit closure function
//   regular function:        Function for implicit closure function
//   constructor, factory:    Function for implicit closure function
//   ffi trampoline function: FfiTrampolineData  (Dart->C)
//   dyn inv forwarder:       Forwarding target, a WSR pointing to it or null
//                            (null can only occur if forwarding target was
//                            dropped)
void Function::set_data(const Object& value) const {
  untag()->set_data<std::memory_order_release>(value.ptr());
}

void Function::set_name(const String& value) const {
  ASSERT(value.IsSymbol());
  untag()->set_name(value.ptr());
}

void Function::set_owner(const Object& value) const {
  ASSERT(!value.IsNull());
  untag()->set_owner(value.ptr());
}

RegExpPtr Function::regexp() const {
  ASSERT(kind() == UntaggedFunction::kIrregexpFunction);
  const Array& pair = Array::Cast(Object::Handle(data()));
  return RegExp::RawCast(pair.At(0));
}

using StickySpecialization = BitField<intptr_t, bool>;
using StringSpecializationCid = BitField<intptr_t,
                                         intptr_t,
                                         StickySpecialization::kNextBit,
                                         UntaggedObject::ClassIdTag::bitsize()>;

intptr_t Function::string_specialization_cid() const {
  ASSERT(kind() == UntaggedFunction::kIrregexpFunction);
  const Array& pair = Array::Cast(Object::Handle(data()));
  return StringSpecializationCid::decode(Smi::Value(Smi::RawCast(pair.At(1))));
}

bool Function::is_sticky_specialization() const {
  ASSERT(kind() == UntaggedFunction::kIrregexpFunction);
  const Array& pair = Array::Cast(Object::Handle(data()));
  return StickySpecialization::decode(Smi::Value(Smi::RawCast(pair.At(1))));
}

void Function::SetRegExpData(const RegExp& regexp,
                             intptr_t string_specialization_cid,
                             bool sticky) const {
  ASSERT(kind() == UntaggedFunction::kIrregexpFunction);
  ASSERT(IsStringClassId(string_specialization_cid));
  ASSERT(data() == Object::null());
  const Array& pair = Array::Handle(Array::New(2, Heap::kOld));
  pair.SetAt(0, regexp);
  pair.SetAt(1, Smi::Handle(Smi::New(StickySpecialization::encode(sticky) |
                                     StringSpecializationCid::encode(
                                         string_specialization_cid))));
  set_data(pair);
}

StringPtr Function::native_name() const {
  ASSERT(is_native());
  const Object& obj = Object::Handle(data());
  ASSERT(obj.IsArray());
  return String::RawCast(Array::Cast(obj).At(0));
}

void Function::set_native_name(const String& value) const {
  ASSERT(is_native());
  const auto& pair = Array::Cast(Object::Handle(data()));
  ASSERT(pair.At(0) == Object::null());
  pair.SetAt(NativeFunctionData::kNativeName, value);
}

InstancePtr Function::GetNativeAnnotation() const {
  ASSERT(is_ffi_native());
  Zone* zone = Thread::Current()->zone();
  auto& pragma_value = Object::Handle(zone);
  Library::FindPragma(dart::Thread::Current(), /*only_core=*/false,
                      Object::Handle(zone, ptr()),
                      String::Handle(zone, Symbols::vm_ffi_native().ptr()),
                      /*multiple=*/false, &pragma_value);
  auto const& native_instance = Instance::Cast(pragma_value);
  ASSERT(!native_instance.IsNull());
#if defined(DEBUG)
  const auto& native_class = Class::Handle(zone, native_instance.clazz());
  ASSERT(String::Handle(zone, native_class.UserVisibleName())
             .Equals(Symbols::FfiNative()));
#endif
  return native_instance.ptr();
}

bool Function::is_old_native() const {
  return is_native() && !is_external();
}

bool Function::is_ffi_native() const {
  return is_native() && is_external();
}

void Function::SetSignature(const FunctionType& value) const {
  set_signature(value);
  ASSERT(NumImplicitParameters() == value.num_implicit_parameters());
  if (IsClosureFunction() && value.IsGeneric()) {
    Zone* zone = Thread::Current()->zone();
    const TypeParameters& type_params =
        TypeParameters::Handle(zone, value.type_parameters());
    const TypeArguments& defaults =
        TypeArguments::Handle(zone, type_params.defaults());
    auto mode = defaults.GetInstantiationMode(zone, this);
    set_default_type_arguments_instantiation_mode(mode);
  }
}

TypeParameterPtr FunctionType::TypeParameterAt(intptr_t index,
                                               Nullability nullability) const {
  ASSERT(index >= 0 && index < NumTypeParameters());
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  TypeParameter& type_param = TypeParameter::Handle(
      zone, TypeParameter::New(*this, NumParentTypeArguments(),
                               NumParentTypeArguments() + index, nullability));
  type_param.SetIsFinalized();
  if (IsFinalized()) {
    type_param ^= type_param.Canonicalize(thread);
  }
  return type_param.ptr();
}

void FunctionType::set_result_type(const AbstractType& value) const {
  ASSERT(!value.IsNull());
  untag()->set_result_type(value.ptr());
}

AbstractTypePtr Function::ParameterTypeAt(intptr_t index) const {
  const Array& types = Array::Handle(parameter_types());
  return AbstractType::RawCast(types.At(index));
}

AbstractTypePtr FunctionType::ParameterTypeAt(intptr_t index) const {
  const Array& parameter_types = Array::Handle(untag()->parameter_types());
  return AbstractType::RawCast(parameter_types.At(index));
}

void FunctionType::SetParameterTypeAt(intptr_t index,
                                      const AbstractType& value) const {
  ASSERT(!value.IsNull());
  const Array& parameter_types = Array::Handle(untag()->parameter_types());
  parameter_types.SetAt(index, value);
}

void FunctionType::set_parameter_types(const Array& value) const {
  ASSERT(value.IsNull() || value.Length() > 0);
  untag()->set_parameter_types(value.ptr());
}

StringPtr Function::ParameterNameAt(intptr_t index) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  if (signature() == FunctionType::null()) {
    // Without the signature, we're guaranteed not to have any name information.
    return Symbols::OptimizedOut().ptr();
  }
#endif
  const intptr_t num_fixed = num_fixed_parameters();
  if (HasOptionalNamedParameters() && index >= num_fixed) {
    const Array& parameter_names =
        Array::Handle(signature()->untag()->named_parameter_names());
    return String::RawCast(parameter_names.At(index - num_fixed));
  }
#if defined(DART_PRECOMPILED_RUNTIME)
  return Symbols::OptimizedOut().ptr();
#else
  const Array& names = Array::Handle(untag()->positional_parameter_names());
  return String::RawCast(names.At(index));
#endif
}

void Function::SetParameterNameAt(intptr_t index, const String& value) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  ASSERT(!value.IsNull() && value.IsSymbol());
  if (HasOptionalNamedParameters() && index >= num_fixed_parameters()) {
    // These should be set on the signature, not the function.
    UNREACHABLE();
  }
  const Array& parameter_names =
      Array::Handle(untag()->positional_parameter_names());
  parameter_names.SetAt(index, value);
#endif
}

#if !defined(DART_PRECOMPILED_RUNTIME)
void Function::set_positional_parameter_names(const Array& value) const {
  ASSERT(value.ptr() == Object::empty_array().ptr() || value.Length() > 0);
  untag()->set_positional_parameter_names(value.ptr());
}
#endif

StringPtr FunctionType::ParameterNameAt(intptr_t index) const {
  const intptr_t num_fixed = num_fixed_parameters();
  if (!HasOptionalNamedParameters() || index < num_fixed) {
    // The positional parameter names are stored on the function, not here.
    UNREACHABLE();
  }
  const Array& parameter_names =
      Array::Handle(untag()->named_parameter_names());
  return String::RawCast(parameter_names.At(index - num_fixed));
}

void FunctionType::SetParameterNameAt(intptr_t index,
                                      const String& value) const {
#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES)
  UNREACHABLE();
#else
  ASSERT(!value.IsNull() && value.IsSymbol());
  const intptr_t num_fixed = num_fixed_parameters();
  if (!HasOptionalNamedParameters() || index < num_fixed) {
    UNREACHABLE();
  }
  const Array& parameter_names =
      Array::Handle(untag()->named_parameter_names());
  parameter_names.SetAt(index - num_fixed, value);
#endif
}

void FunctionType::set_named_parameter_names(const Array& value) const {
  ASSERT(value.ptr() == Object::empty_array().ptr() || value.Length() > 0);
  untag()->set_named_parameter_names(value.ptr());
}

void Function::CreateNameArray(Heap::Space space) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  const intptr_t num_positional_params =
      num_fixed_parameters() + NumOptionalPositionalParameters();
  if (num_positional_params == 0) {
    set_positional_parameter_names(Object::empty_array());
  } else {
    set_positional_parameter_names(
        Array::Handle(Array::New(num_positional_params, space)));
  }
#endif
}

void FunctionType::CreateNameArrayIncludingFlags(Heap::Space space) const {
#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES)
  UNREACHABLE();
#else
  const intptr_t num_named_parameters = NumOptionalNamedParameters();
  if (num_named_parameters == 0) {
    return set_named_parameter_names(Object::empty_array());
  }
  // Currently, we only store flags for named parameters.
  const intptr_t last_index = (num_named_parameters - 1) /
                              compiler::target::kNumParameterFlagsPerElement;
  const intptr_t num_flag_slots = last_index + 1;
  intptr_t num_total_slots = num_named_parameters + num_flag_slots;
  auto& array = Array::Handle(Array::New(num_total_slots, space));
  // Set flag slots to Smi 0 before handing off.
  auto& empty_flags_smi = Smi::Handle(Smi::New(0));
  for (intptr_t i = num_named_parameters; i < num_total_slots; i++) {
    array.SetAt(i, empty_flags_smi);
  }
  set_named_parameter_names(array);
#endif
}

intptr_t FunctionType::GetRequiredFlagIndex(intptr_t index,
                                            intptr_t* flag_mask) const {
  // If these calculations change, also change
  // FlowGraphBuilder::BuildClosureCallHasRequiredNamedArgumentsCheck.
  ASSERT(HasOptionalNamedParameters());
  ASSERT(flag_mask != nullptr);
  ASSERT(index >= num_fixed_parameters());
  index -= num_fixed_parameters();
  *flag_mask = (1 << compiler::target::kRequiredNamedParameterFlag)
               << ((static_cast<uintptr_t>(index) %
                    compiler::target::kNumParameterFlagsPerElement) *
                   compiler::target::kNumParameterFlags);
  return NumOptionalNamedParameters() +
         index / compiler::target::kNumParameterFlagsPerElement;
}

bool Function::HasRequiredNamedParameters() const {
#if defined(DART_PRECOMPILED_RUNTIME)
  if (signature() == FunctionType::null()) {
    // Signatures for functions with required named parameters are not dropped.
    return false;
  }
#endif
  return FunctionType::Handle(signature()).HasRequiredNamedParameters();
}

bool Function::IsRequiredAt(intptr_t index) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  if (signature() == FunctionType::null()) {
    // Signature is not dropped in aot when any named parameter is required.
    return false;
  }
#endif
  if (!HasOptionalNamedParameters() || index < num_fixed_parameters()) {
    return false;
  }
  const FunctionType& sig = FunctionType::Handle(signature());
  return sig.IsRequiredAt(index);
}

bool FunctionType::IsRequiredAt(intptr_t index) const {
  if (!HasOptionalNamedParameters() || index < num_fixed_parameters()) {
    return false;
  }
  intptr_t flag_mask;
  const intptr_t flag_index = GetRequiredFlagIndex(index, &flag_mask);
  const Array& parameter_names =
      Array::Handle(untag()->named_parameter_names());
  if (flag_index >= parameter_names.Length()) {
    return false;
  }
  const intptr_t flags =
      Smi::Value(Smi::RawCast(parameter_names.At(flag_index)));
  return (flags & flag_mask) != 0;
}

void FunctionType::SetIsRequiredAt(intptr_t index) const {
#if defined(DART_PRECOMPILER_RUNTIME)
  UNREACHABLE();
#else
  intptr_t flag_mask;
  const intptr_t flag_index = GetRequiredFlagIndex(index, &flag_mask);
  const Array& parameter_names =
      Array::Handle(untag()->named_parameter_names());
  ASSERT(flag_index < parameter_names.Length());
  const intptr_t flags =
      Smi::Value(Smi::RawCast(parameter_names.At(flag_index)));
  parameter_names.SetAt(flag_index, Smi::Handle(Smi::New(flags | flag_mask)));
#endif
}

void FunctionType::FinalizeNameArray() const {
#if defined(DART_PRECOMPILER_RUNTIME)
  UNREACHABLE();
#else
  const intptr_t num_named_parameters = NumOptionalNamedParameters();
  if (num_named_parameters == 0) {
    ASSERT(untag()->named_parameter_names() == Object::empty_array().ptr());
    return;
  }
  const Array& parameter_names =
      Array::Handle(untag()->named_parameter_names());
  // Truncate the parameter names array to remove unused flags from the end.
  intptr_t last_used = parameter_names.Length() - 1;
  for (; last_used >= num_named_parameters; --last_used) {
    if (Smi::Value(Smi::RawCast(parameter_names.At(last_used))) != 0) {
      break;
    }
  }
  parameter_names.Truncate(last_used + 1);
#endif
}

bool FunctionType::HasRequiredNamedParameters() const {
  const intptr_t num_named_params = NumOptionalNamedParameters();
  if (num_named_params == 0) return false;
  // Check for flag slots in the named parameter names array.
  const auto& parameter_names = Array::Handle(named_parameter_names());
  ASSERT(!parameter_names.IsNull());
  return parameter_names.Length() > num_named_params;
}

static void ReportTooManyTypeParameters(const FunctionType& sig) {
  Report::MessageF(Report::kError, Script::Handle(), TokenPosition::kNoSource,
                   Report::AtLocation,
                   "too many type parameters declared in signature '%s' or in "
                   "its enclosing signatures",
                   sig.ToUserVisibleCString());
  UNREACHABLE();
}

void FunctionType::SetTypeParameters(const TypeParameters& value) const {
  untag()->set_type_parameters(value.ptr());
  const intptr_t count = value.Length();
  if (!UntaggedFunctionType::PackedNumTypeParameters::is_valid(count)) {
    ReportTooManyTypeParameters(*this);
  }
  untag()->packed_type_parameter_counts_.Update<PackedNumTypeParameters>(count);
}

void FunctionType::SetNumParentTypeArguments(intptr_t value) const {
  ASSERT(value >= 0);
  if (!PackedNumParentTypeArguments::is_valid(value)) {
    ReportTooManyTypeParameters(*this);
  }
  untag()->packed_type_parameter_counts_.Update<PackedNumParentTypeArguments>(
      value);
}

bool Function::IsGeneric() const {
  return FunctionType::IsGeneric(signature());
}
intptr_t Function::NumTypeParameters() const {
  return FunctionType::NumTypeParametersOf(signature());
}
intptr_t Function::NumParentTypeArguments() const {
  return FunctionType::NumParentTypeArgumentsOf(signature());
}
intptr_t Function::NumTypeArguments() const {
  return FunctionType::NumTypeArgumentsOf(signature());
}
intptr_t Function::num_fixed_parameters() const {
  return FunctionType::NumFixedParametersOf(signature());
}
bool Function::HasOptionalParameters() const {
  return FunctionType::HasOptionalParameters(signature());
}
bool Function::HasOptionalNamedParameters() const {
  return FunctionType::HasOptionalNamedParameters(signature());
}
bool Function::HasOptionalPositionalParameters() const {
  return FunctionType::HasOptionalPositionalParameters(signature());
}
intptr_t Function::NumOptionalParameters() const {
  return FunctionType::NumOptionalParametersOf(signature());
}
intptr_t Function::NumOptionalPositionalParameters() const {
  return FunctionType::NumOptionalPositionalParametersOf(signature());
}
intptr_t Function::NumOptionalNamedParameters() const {
  return FunctionType::NumOptionalNamedParametersOf(signature());
}
intptr_t Function::NumParameters() const {
  return FunctionType::NumParametersOf(signature());
}

TypeParameterPtr Function::TypeParameterAt(intptr_t index,
                                           Nullability nullability) const {
  const FunctionType& sig = FunctionType::Handle(signature());
  return sig.TypeParameterAt(index, nullability);
}

void Function::set_kind(UntaggedFunction::Kind value) const {
  untag()->kind_tag_.Update<KindBits>(value);
}

void Function::set_modifier(UntaggedFunction::AsyncModifier value) const {
  untag()->kind_tag_.Update<ModifierBits>(value);
}

void Function::set_recognized_kind(MethodRecognizer::Kind value) const {
  // Prevent multiple settings of kind.
  ASSERT((value == MethodRecognizer::kUnknown) || !IsRecognized());
  untag()->kind_tag_.Update<RecognizedBits>(value);
}

void Function::set_token_pos(TokenPosition token_pos) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  ASSERT(!token_pos.IsClassifying() || IsMethodExtractor());
  StoreNonPointer(&untag()->token_pos_, token_pos);
#endif
}

void Function::set_kind_tag(uint32_t value) const {
  untag()->kind_tag_ = value;
}

bool Function::is_eval_function() const {
  if (data()->IsArray()) {
    const intptr_t len = Array::LengthOf(Array::RawCast(data()));
    return len == static_cast<intptr_t>(EvalFunctionData::kLength);
  }
  return false;
}

bool Function::IsOptimizable() const {
  if (FLAG_precompiled_mode) {
    return true;
  }
  if (ForceOptimize()) return true;
  if (is_old_native()) {
    // Native methods don't need to be optimized.
    return false;
  }
  if (is_optimizable() && (script() != Script::null())) {
    // Additional check needed for implicit getters.
    return (unoptimized_code() == Object::null()) ||
           (Code::Handle(unoptimized_code()).Size() <
            FLAG_huge_method_cutoff_in_code_size);
  }
  return false;
}

bool Function::IsTypedDataViewFactory() const {
  switch (recognized_kind()) {
    case MethodRecognizer::kTypedData_ByteDataView_factory:
    case MethodRecognizer::kTypedData_Int8ArrayView_factory:
    case MethodRecognizer::kTypedData_Uint8ArrayView_factory:
    case MethodRecognizer::kTypedData_Uint8ClampedArrayView_factory:
    case MethodRecognizer::kTypedData_Int16ArrayView_factory:
    case MethodRecognizer::kTypedData_Uint16ArrayView_factory:
    case MethodRecognizer::kTypedData_Int32ArrayView_factory:
    case MethodRecognizer::kTypedData_Uint32ArrayView_factory:
    case MethodRecognizer::kTypedData_Int64ArrayView_factory:
    case MethodRecognizer::kTypedData_Uint64ArrayView_factory:
    case MethodRecognizer::kTypedData_Float32ArrayView_factory:
    case MethodRecognizer::kTypedData_Float64ArrayView_factory:
    case MethodRecognizer::kTypedData_Float32x4ArrayView_factory:
    case MethodRecognizer::kTypedData_Int32x4ArrayView_factory:
    case MethodRecognizer::kTypedData_Float64x2ArrayView_factory:
      return true;
    default:
      return false;
  }
}

bool Function::IsUnmodifiableTypedDataViewFactory() const {
  switch (recognized_kind()) {
    case MethodRecognizer::kTypedData_UnmodifiableByteDataView_factory:
    case MethodRecognizer::kTypedData_UnmodifiableInt8ArrayView_factory:
    case MethodRecognizer::kTypedData_UnmodifiableUint8ArrayView_factory:
    case MethodRecognizer::kTypedData_UnmodifiableUint8ClampedArrayView_factory:
    case MethodRecognizer::kTypedData_UnmodifiableInt16ArrayView_factory:
    case MethodRecognizer::kTypedData_UnmodifiableUint16ArrayView_factory:
    case MethodRecognizer::kTypedData_UnmodifiableInt32ArrayView_factory:
    case MethodRecognizer::kTypedData_UnmodifiableUint32ArrayView_factory:
    case MethodRecognizer::kTypedData_UnmodifiableInt64ArrayView_factory:
    case MethodRecognizer::kTypedData_UnmodifiableUint64ArrayView_factory:
    case MethodRecognizer::kTypedData_UnmodifiableFloat32ArrayView_factory:
    case MethodRecognizer::kTypedData_UnmodifiableFloat64ArrayView_factory:
    case MethodRecognizer::kTypedData_UnmodifiableFloat32x4ArrayView_factory:
    case MethodRecognizer::kTypedData_UnmodifiableInt32x4ArrayView_factory:
    case MethodRecognizer::kTypedData_UnmodifiableFloat64x2ArrayView_factory:
      return true;
    default:
      return false;
  }
}

static bool InVmTests(const Function& function) {
#if defined(TESTING)
  return true;
#else
  auto* zone = Thread::Current()->zone();
  const auto& cls = Class::Handle(zone, function.Owner());
  const auto& lib = Library::Handle(zone, cls.library());
  const auto& url = String::Handle(zone, lib.url());
  const bool in_vm_tests =
      strstr(url.ToCString(), "runtime/tests/vm/") != nullptr;
  return in_vm_tests;
#endif
}

bool Function::ForceOptimize() const {
  if (RecognizedKindForceOptimize() || IsFfiCallClosure() ||
      IsFfiCallbackTrampoline() || is_ffi_native() ||
      IsTypedDataViewFactory() || IsUnmodifiableTypedDataViewFactory()) {
    return true;
  }

  if (!has_pragma()) return false;

  const bool has_vm_pragma = Library::FindPragma(
      Thread::Current(), false, *this, Symbols::vm_force_optimize());
  if (!has_vm_pragma) return false;

  // For run_vm_tests and runtime/tests/vm allow marking arbitrary functions as
  // force-optimize via `@pragma('vm:force-optimize')`.
  return InVmTests(*this);
}

bool Function::IsPreferInline() const {
  if (!has_pragma()) return false;

  return Library::FindPragma(Thread::Current(), /*only_core=*/false, *this,
                             Symbols::vm_prefer_inline());
}

bool Function::IsIdempotent() const {
  if (!has_pragma()) return false;

#if defined(TESTING)
  const bool kAllowOnlyForCoreLibFunctions = false;
#else
  const bool kAllowOnlyForCoreLibFunctions = true;
#endif  // defined(TESTING)

  return Library::FindPragma(Thread::Current(), kAllowOnlyForCoreLibFunctions,
                             *this, Symbols::vm_idempotent());
}

bool Function::IsCachableIdempotent() const {
  if (!has_pragma()) return false;

  const bool has_vm_pragma =
      Library::FindPragma(Thread::Current(), /*only_core=*/false, *this,
                          Symbols::vm_cachable_idempotent());
  if (!has_vm_pragma) return false;

  // For run_vm_tests and runtime/tests/vm allow marking arbitrary functions.
  return InVmTests(*this);
}

bool Function::IsFfiCallClosure() const {
  if (!IsNonImplicitClosureFunction()) return false;
  if (!has_pragma()) return false;
  return Library::FindPragma(Thread::Current(), /*only_core=*/false, *this,
                             Symbols::vm_ffi_call_closure());
}

InstancePtr Function::GetFfiCallClosurePragmaValue() const {
  ASSERT(IsFfiCallClosure());
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  auto& pragma_value = Object::Handle(zone);
  Library::FindPragma(thread, /*only_core=*/false, *this,
                      Symbols::vm_ffi_call_closure(),
                      /*multiple=*/false, &pragma_value);
  ASSERT(!pragma_value.IsNull());
  return Instance::Cast(pragma_value).ptr();
}

bool Function::RecognizedKindForceOptimize() const {
  switch (recognized_kind()) {
    // Uses unboxed/untagged data not supported in unoptimized, or uses
    // LoadIndexed/StoreIndexed/MemoryCopy instructions with typed data
    // arrays, which requires optimization for payload extraction.
    case MethodRecognizer::kObjectArrayGetIndexed:
    case MethodRecognizer::kGrowableArrayGetIndexed:
#define TYPED_DATA_GET_INDEXED_CASES(clazz)                                    \
  case MethodRecognizer::k##clazz##ArrayGetIndexed:                            \
    FALL_THROUGH;                                                              \
  case MethodRecognizer::kExternal##clazz##ArrayGetIndexed:                    \
    FALL_THROUGH;                                                              \
  case MethodRecognizer::k##clazz##ArrayViewGetIndexed:                        \
    FALL_THROUGH;
      DART_CLASS_LIST_TYPED_DATA(TYPED_DATA_GET_INDEXED_CASES)
#undef TYPED_DATA_GET_INDEXED_CASES
    case MethodRecognizer::kCopyRangeFromUint8ListToOneByteString:
    case MethodRecognizer::kFinalizerBase_getIsolateFinalizers:
    case MethodRecognizer::kFinalizerBase_setIsolate:
    case MethodRecognizer::kFinalizerBase_setIsolateFinalizers:
    case MethodRecognizer::kFinalizerEntry_getExternalSize:
    case MethodRecognizer::kExtensionStreamHasListener:
    case MethodRecognizer::kFfiLoadInt8:
    case MethodRecognizer::kFfiLoadInt16:
    case MethodRecognizer::kFfiLoadInt32:
    case MethodRecognizer::kFfiLoadInt64:
    case MethodRecognizer::kFfiLoadUint8:
    case MethodRecognizer::kFfiLoadUint16:
    case MethodRecognizer::kFfiLoadUint32:
    case MethodRecognizer::kFfiLoadUint64:
    case MethodRecognizer::kFfiLoadFloat:
    case MethodRecognizer::kFfiLoadFloatUnaligned:
    case MethodRecognizer::kFfiLoadDouble:
    case MethodRecognizer::kFfiLoadDoubleUnaligned:
    case MethodRecognizer::kFfiLoadPointer:
    case MethodRecognizer::kFfiStoreInt8:
    case MethodRecognizer::kFfiStoreInt16:
    case MethodRecognizer::kFfiStoreInt32:
    case MethodRecognizer::kFfiStoreInt64:
    case MethodRecognizer::kFfiStoreUint8:
    case MethodRecognizer::kFfiStoreUint16:
    case MethodRecognizer::kFfiStoreUint32:
    case MethodRecognizer::kFfiStoreUint64:
    case MethodRecognizer::kFfiStoreFloat:
    case MethodRecognizer::kFfiStoreFloatUnaligned:
    case MethodRecognizer::kFfiStoreDouble:
    case MethodRecognizer::kFfiStoreDoubleUnaligned:
    case MethodRecognizer::kFfiStorePointer:
    case MethodRecognizer::kFfiFromAddress:
    case MethodRecognizer::kFfiGetAddress:
    case MethodRecognizer::kFfiAsExternalTypedDataInt8:
    case MethodRecognizer::kFfiAsExternalTypedDataInt16:
    case MethodRecognizer::kFfiAsExternalTypedDataInt32:
    case MethodRecognizer::kFfiAsExternalTypedDataInt64:
    case MethodRecognizer::kFfiAsExternalTypedDataUint8:
    case MethodRecognizer::kFfiAsExternalTypedDataUint16:
    case MethodRecognizer::kFfiAsExternalTypedDataUint32:
    case MethodRecognizer::kFfiAsExternalTypedDataUint64:
    case MethodRecognizer::kFfiAsExternalTypedDataFloat:
    case MethodRecognizer::kFfiAsExternalTypedDataDouble:
    case MethodRecognizer::kGetNativeField:
    case MethodRecognizer::kRecord_fieldNames:
    case MethodRecognizer::kRecord_numFields:
    case MethodRecognizer::kStringBaseCodeUnitAt:
    case MethodRecognizer::kUtf8DecoderScan:
    case MethodRecognizer::kDouble_hashCode:
    case MethodRecognizer::kTypedList_GetInt8:
    case MethodRecognizer::kTypedList_SetInt8:
    case MethodRecognizer::kTypedList_GetUint8:
    case MethodRecognizer::kTypedList_SetUint8:
    case MethodRecognizer::kTypedList_GetInt16:
    case MethodRecognizer::kTypedList_SetInt16:
    case MethodRecognizer::kTypedList_GetUint16:
    case MethodRecognizer::kTypedList_SetUint16:
    case MethodRecognizer::kTypedList_GetInt32:
    case MethodRecognizer::kTypedList_SetInt32:
    case MethodRecognizer::kTypedList_GetUint32:
    case MethodRecognizer::kTypedList_SetUint32:
    case MethodRecognizer::kTypedList_GetInt64:
    case MethodRecognizer::kTypedList_SetInt64:
    case MethodRecognizer::kTypedList_GetUint64:
    case MethodRecognizer::kTypedList_SetUint64:
    case MethodRecognizer::kTypedList_GetFloat32:
    case MethodRecognizer::kTypedList_SetFloat32:
    case MethodRecognizer::kTypedList_GetFloat64:
    case MethodRecognizer::kTypedList_SetFloat64:
    case MethodRecognizer::kTypedList_GetInt32x4:
    case MethodRecognizer::kTypedList_SetInt32x4:
    case MethodRecognizer::kTypedList_GetFloat32x4:
    case MethodRecognizer::kTypedList_SetFloat32x4:
    case MethodRecognizer::kTypedList_GetFloat64x2:
    case MethodRecognizer::kTypedList_SetFloat64x2:
    case MethodRecognizer::kTypedData_memMove1:
    case MethodRecognizer::kTypedData_memMove2:
    case MethodRecognizer::kTypedData_memMove4:
    case MethodRecognizer::kTypedData_memMove8:
    case MethodRecognizer::kTypedData_memMove16:
    case MethodRecognizer::kMemCopy:
    // Prevent the GC from running so that the operation is atomic from
    // a GC point of view. Always double check implementation in
    // kernel_to_il.cc that no GC can happen in between the relevant IL
    // instructions.
    // TODO(https://dartbug.com/48527): Support inlining.
    case MethodRecognizer::kFinalizerBase_exchangeEntriesCollectedWithNull:
    // Both unboxed/untagged data and atomic-to-GC operation.
    case MethodRecognizer::kFinalizerEntry_allocate:
      return true;
    default:
      return false;
  }
}

#if !defined(DART_PRECOMPILED_RUNTIME)
bool Function::CanBeInlined() const {
  if (ForceOptimize()) {
    if (IsFfiCallClosure() || IsFfiCallbackTrampoline() || is_ffi_native()) {
      // We currently don't support inlining FFI trampolines. Some of them
      // are naturally non-inlinable because they contain a try/catch block,
      // but this condition is broader than strictly necessary.
      // The work necessary for inlining FFI trampolines is tracked by
      // http://dartbug.com/45055.
      return false;
    }
    if (CompilerState::Current().is_aot()) {
      return true;
    }
    // Inlining of force-optimized functions requires target function to be
    // idempotent becase if deoptimization is needed in inlined body, the
    // execution of the force-optimized will be restarted at the beginning of
    // the function.
    ASSERT(!IsPreferInline() || IsIdempotent());
    return IsIdempotent();
  }

  if (HasBreakpoint()) {
    return false;
  }

  return is_inlinable();
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

intptr_t Function::NumImplicitParameters() const {
  const UntaggedFunction::Kind k = kind();
  if (k == UntaggedFunction::kConstructor) {
    // Type arguments for factory; instance for generative constructor.
    return 1;
  }
  if ((k == UntaggedFunction::kClosureFunction) ||
      (k == UntaggedFunction::kImplicitClosureFunction) ||
      (k == UntaggedFunction::kFfiTrampoline)) {
    return 1;  // Closure object.
  }
  if (!is_static()) {
    // Closure functions defined inside instance (i.e. non-static) functions are
    // marked as non-static, but they do not have a receiver.
    // Closures are handled above.
    ASSERT((k != UntaggedFunction::kClosureFunction) &&
           (k != UntaggedFunction::kImplicitClosureFunction));
    return 1;  // Receiver.
  }
  return 0;  // No implicit parameters.
}

bool Function::AreValidArgumentCounts(intptr_t num_type_arguments,
                                      intptr_t num_arguments,
                                      intptr_t num_named_arguments,
                                      String* error_message) const {
  if ((num_type_arguments != 0) &&
      (num_type_arguments != NumTypeParameters())) {
    if (error_message != nullptr) {
      const intptr_t kMessageBufferSize = 64;
      char message_buffer[kMessageBufferSize];
      Utils::SNPrint(message_buffer, kMessageBufferSize,
                     "%" Pd " type arguments passed, but %" Pd " expected",
                     num_type_arguments, NumTypeParameters());
      // Allocate in old space because it can be invoked in background
      // optimizing compilation.
      *error_message = String::New(message_buffer, Heap::kOld);
    }
    return false;  // Too many type arguments.
  }
  if (num_named_arguments > NumOptionalNamedParameters()) {
    if (error_message != nullptr) {
      const intptr_t kMessageBufferSize = 64;
      char message_buffer[kMessageBufferSize];
      Utils::SNPrint(message_buffer, kMessageBufferSize,
                     "%" Pd " named passed, at most %" Pd " expected",
                     num_named_arguments, NumOptionalNamedParameters());
      // Allocate in old space because it can be invoked in background
      // optimizing compilation.
      *error_message = String::New(message_buffer, Heap::kOld);
    }
    return false;  // Too many named arguments.
  }
  const intptr_t num_pos_args = num_arguments - num_named_arguments;
  const intptr_t num_opt_pos_params = NumOptionalPositionalParameters();
  const intptr_t num_pos_params = num_fixed_parameters() + num_opt_pos_params;
  if (num_pos_args > num_pos_params) {
    if (error_message != nullptr) {
      const intptr_t kMessageBufferSize = 64;
      char message_buffer[kMessageBufferSize];
      // Hide implicit parameters to the user.
      const intptr_t num_hidden_params = NumImplicitParameters();
      Utils::SNPrint(message_buffer, kMessageBufferSize,
                     "%" Pd "%s passed, %s%" Pd " expected",
                     num_pos_args - num_hidden_params,
                     num_opt_pos_params > 0 ? " positional" : "",
                     num_opt_pos_params > 0 ? "at most " : "",
                     num_pos_params - num_hidden_params);
      // Allocate in old space because it can be invoked in background
      // optimizing compilation.
      *error_message = String::New(message_buffer, Heap::kOld);
    }
    return false;  // Too many fixed and/or positional arguments.
  }
  if (num_pos_args < num_fixed_parameters()) {
    if (error_message != nullptr) {
      const intptr_t kMessageBufferSize = 64;
      char message_buffer[kMessageBufferSize];
      // Hide implicit parameters to the user.
      const intptr_t num_hidden_params = NumImplicitParameters();
      Utils::SNPrint(message_buffer, kMessageBufferSize,
                     "%" Pd "%s passed, %s%" Pd " expected",
                     num_pos_args - num_hidden_params,
                     num_opt_pos_params > 0 ? " positional" : "",
                     num_opt_pos_params > 0 ? "at least " : "",
                     num_fixed_parameters() - num_hidden_params);
      // Allocate in old space because it can be invoked in background
      // optimizing compilation.
      *error_message = String::New(message_buffer, Heap::kOld);
    }
    return false;  // Too few fixed and/or positional arguments.
  }
  return true;
}

bool Function::AreValidArguments(intptr_t num_type_arguments,
                                 intptr_t num_arguments,
                                 const Array& argument_names,
                                 String* error_message) const {
  const Array& args_desc_array = Array::Handle(ArgumentsDescriptor::NewBoxed(
      num_type_arguments, num_arguments, argument_names, Heap::kNew));
  ArgumentsDescriptor args_desc(args_desc_array);
  return AreValidArguments(args_desc, error_message);
}

bool Function::AreValidArguments(const ArgumentsDescriptor& args_desc,
                                 String* error_message) const {
  const intptr_t num_type_arguments = args_desc.TypeArgsLen();
  const intptr_t num_arguments = args_desc.Count();
  const intptr_t num_named_arguments = args_desc.NamedCount();

  if (!AreValidArgumentCounts(num_type_arguments, num_arguments,
                              num_named_arguments, error_message)) {
    return false;
  }
  // Verify that all argument names are valid parameter names.
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  String& argument_name = String::Handle(zone);
  String& parameter_name = String::Handle(zone);
  const intptr_t num_positional_args = num_arguments - num_named_arguments;
  const intptr_t num_parameters = NumParameters();
  for (intptr_t i = 0; i < num_named_arguments; i++) {
    argument_name = args_desc.NameAt(i);
    ASSERT(argument_name.IsSymbol());
    bool found = false;
    for (intptr_t j = num_positional_args; j < num_parameters; j++) {
      parameter_name = ParameterNameAt(j);
      ASSERT(parameter_name.IsSymbol());
      if (argument_name.Equals(parameter_name)) {
        found = true;
        break;
      }
    }
    if (!found) {
      if (error_message != nullptr) {
        const intptr_t kMessageBufferSize = 64;
        char message_buffer[kMessageBufferSize];
        Utils::SNPrint(message_buffer, kMessageBufferSize,
                       "no optional formal parameter named '%s'",
                       argument_name.ToCString());
        *error_message = String::New(message_buffer);
      }
      return false;
    }
  }
  // Verify that all required named parameters are filled.
  for (intptr_t j = num_parameters - NumOptionalNamedParameters();
       j < num_parameters; j++) {
    if (IsRequiredAt(j)) {
      parameter_name = ParameterNameAt(j);
      ASSERT(parameter_name.IsSymbol());
      bool found = false;
      for (intptr_t i = 0; i < num_named_arguments; i++) {
        argument_name = args_desc.NameAt(i);
        ASSERT(argument_name.IsSymbol());
        if (argument_name.Equals(parameter_name)) {
          found = true;
          break;
        }
      }
      if (!found) {
        if (error_message != nullptr) {
          const intptr_t kMessageBufferSize = 64;
          char message_buffer[kMessageBufferSize];
          Utils::SNPrint(message_buffer, kMessageBufferSize,
                         "missing required named parameter '%s'",
                         parameter_name.ToCString());
          *error_message = String::New(message_buffer);
        }
        return false;
      }
    }
  }
  return true;
}

// Retrieves the function type arguments, if any. This could be explicitly
// passed type from the arguments array, delayed type arguments in closures,
// or instantiated bounds for the type parameters if no other source for
// function type arguments are found.
static TypeArgumentsPtr RetrieveFunctionTypeArguments(
    Thread* thread,
    Zone* zone,
    const Function& function,
    const Instance& receiver,
    const TypeArguments& instantiator_type_args,
    const Array& args,
    const ArgumentsDescriptor& args_desc) {
  ASSERT(!function.IsNull());

  const intptr_t kNumCurrentTypeArgs = function.NumTypeParameters();
  const intptr_t kNumParentTypeArgs = function.NumParentTypeArguments();
  const intptr_t kNumTypeArgs = kNumCurrentTypeArgs + kNumParentTypeArgs;
  // Non-generic functions don't receive type arguments.
  if (kNumTypeArgs == 0) return Object::empty_type_arguments().ptr();
  // Closure functions require that the receiver be provided (and is a closure).
  ASSERT(!function.IsClosureFunction() || receiver.IsClosure());

  // Only closure functions should have possibly generic parents.
  ASSERT(function.IsClosureFunction() || kNumParentTypeArgs == 0);
  const auto& parent_type_args =
      function.IsClosureFunction()
          ? TypeArguments::Handle(
                zone, Closure::Cast(receiver).function_type_arguments())
          : Object::empty_type_arguments();
  // We don't try to instantiate the parent type parameters to their bounds
  // if not provided or check any closed-over type arguments against the parent
  // type parameter bounds (since they have been type checked already).
  if (kNumCurrentTypeArgs == 0) return parent_type_args.ptr();

  auto& function_type_args = TypeArguments::Handle(zone);
  // First check for delayed type arguments before using either provided or
  // default type arguments.
  bool has_delayed_type_args = false;
  if (function.IsClosureFunction()) {
    const auto& closure = Closure::Cast(receiver);
    function_type_args = closure.delayed_type_arguments();
    has_delayed_type_args =
        function_type_args.ptr() != Object::empty_type_arguments().ptr();
  }

  if (args_desc.TypeArgsLen() > 0) {
    // We should never end up here when the receiver is a closure with delayed
    // type arguments unless this dynamically called closure function was
    // retrieved directly from the closure instead of going through
    // DartEntry::ResolveCallable, which appropriately checks for this case.
    ASSERT(!has_delayed_type_args);
    function_type_args ^= args.At(0);
  } else if (!has_delayed_type_args) {
    // We have no explicitly provided function type arguments, so instantiate
    // the type parameters to bounds or replace as appropriate.
    function_type_args = function.DefaultTypeArguments(zone);
    auto const mode =
        function.IsClosureFunction()
            ? function.default_type_arguments_instantiation_mode()
            : function_type_args.GetInstantiationMode(zone, &function);
    switch (mode) {
      case InstantiationMode::kIsInstantiated:
        // Nothing left to do.
        break;
      case InstantiationMode::kNeedsInstantiation:
        function_type_args = function_type_args.InstantiateAndCanonicalizeFrom(
            instantiator_type_args, parent_type_args);
        break;
      case InstantiationMode::kSharesInstantiatorTypeArguments:
        function_type_args = instantiator_type_args.ptr();
        break;
      case InstantiationMode::kSharesFunctionTypeArguments:
        function_type_args = parent_type_args.ptr();
        break;
    }
  }

  return function_type_args.Prepend(zone, parent_type_args, kNumParentTypeArgs,
                                    kNumTypeArgs);
}

// Retrieves the instantiator type arguments, if any, from the receiver.
static TypeArgumentsPtr RetrieveInstantiatorTypeArguments(
    Zone* zone,
    const Function& function,
    const Instance& receiver) {
  if (function.IsClosureFunction()) {
    ASSERT(receiver.IsClosure());
    const auto& closure = Closure::Cast(receiver);
    return closure.instantiator_type_arguments();
  }
  if (!receiver.IsNull()) {
    const auto& cls = Class::Handle(zone, receiver.clazz());
    if (cls.NumTypeArguments() > 0) {
      return receiver.GetTypeArguments();
    }
  }
  return Object::empty_type_arguments().ptr();
}

ObjectPtr Function::DoArgumentTypesMatch(
    const Array& args,
    const ArgumentsDescriptor& args_desc) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  if (signature() == FunctionType::null()) {
    // Precompiler deleted signature because of missing entry point pragma.
    return EntryPointFunctionInvocationError(*this);
  }
#endif
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  auto& receiver = Instance::Handle(zone);
  if (IsClosureFunction() || HasThisParameter()) {
    receiver ^= args.At(args_desc.FirstArgIndex());
  }
  const auto& instantiator_type_arguments = TypeArguments::Handle(
      zone, RetrieveInstantiatorTypeArguments(zone, *this, receiver));
  return Function::DoArgumentTypesMatch(args, args_desc,
                                        instantiator_type_arguments);
}

ObjectPtr Function::DoArgumentTypesMatch(
    const Array& args,
    const ArgumentsDescriptor& args_desc,
    const TypeArguments& instantiator_type_arguments) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  if (signature() == FunctionType::null()) {
    // Precompiler deleted signature because of missing entry point pragma.
    return EntryPointFunctionInvocationError(*this);
  }
#endif
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  auto& receiver = Instance::Handle(zone);
  if (IsClosureFunction() || HasThisParameter()) {
    receiver ^= args.At(args_desc.FirstArgIndex());
  }

  const auto& function_type_arguments = TypeArguments::Handle(
      zone, RetrieveFunctionTypeArguments(thread, zone, *this, receiver,
                                          instantiator_type_arguments, args,
                                          args_desc));
  return Function::DoArgumentTypesMatch(
      args, args_desc, instantiator_type_arguments, function_type_arguments);
}

ObjectPtr Function::DoArgumentTypesMatch(
    const Array& args,
    const ArgumentsDescriptor& args_desc,
    const TypeArguments& instantiator_type_arguments,
    const TypeArguments& function_type_arguments) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  if (signature() == FunctionType::null()) {
    // Precompiler deleted signature because of missing entry point pragma.
    return EntryPointFunctionInvocationError(*this);
  }
#endif
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  // Perform any non-covariant bounds checks on the provided function type
  // arguments to make sure they are appropriate subtypes of the bounds.
  const intptr_t kNumLocalTypeArgs = NumTypeParameters();
  if (kNumLocalTypeArgs > 0) {
    const intptr_t kNumParentTypeArgs = NumParentTypeArguments();
    ASSERT(function_type_arguments.HasCount(kNumParentTypeArgs +
                                            kNumLocalTypeArgs));
    const auto& params = TypeParameters::Handle(zone, type_parameters());
    // No checks are needed if all bounds are dynamic.
    if (!params.AllDynamicBounds()) {
      auto& param = AbstractType::Handle(zone);
      auto& bound = AbstractType::Handle(zone);
      for (intptr_t i = 0; i < kNumLocalTypeArgs; i++) {
        bound = params.BoundAt(i);
        // Only perform non-covariant checks where the bound is not
        // the top type.
        if (params.IsGenericCovariantImplAt(i) ||
            bound.IsTopTypeForSubtyping()) {
          continue;
        }
        param = TypeParameterAt(i);
        if (!AbstractType::InstantiateAndTestSubtype(
                &param, &bound, instantiator_type_arguments,
                function_type_arguments)) {
          const auto& names = Array::Handle(zone, params.names());
          auto& name = String::Handle(zone);
          name ^= names.At(i);
          return Error::RawCast(
              ThrowTypeError(token_pos(), param, bound, name));
        }
      }
    }
  } else {
    ASSERT(function_type_arguments.HasCount(NumParentTypeArguments()));
  }

  AbstractType& type = AbstractType::Handle(zone);
  Instance& argument = Instance::Handle(zone);

  auto check_argument = [](const Instance& argument, const AbstractType& type,
                           const TypeArguments& instantiator_type_args,
                           const TypeArguments& function_type_args) -> bool {
    // If the argument type is the top type, no need to check.
    if (type.IsTopTypeForSubtyping()) return true;
    return argument.IsInstanceOf(type, instantiator_type_args,
                                 function_type_args);
  };

  // Check types of the provided arguments against the expected parameter types.
  const intptr_t arg_offset = args_desc.FirstArgIndex();
  // Only check explicit arguments.
  const intptr_t arg_start = arg_offset + NumImplicitParameters();
  const intptr_t end_positional_args = arg_offset + args_desc.PositionalCount();
  for (intptr_t arg_index = arg_start; arg_index < end_positional_args;
       ++arg_index) {
    argument ^= args.At(arg_index);
    // Adjust for type arguments when they're present.
    const intptr_t param_index = arg_index - arg_offset;
    type = ParameterTypeAt(param_index);
    if (!check_argument(argument, type, instantiator_type_arguments,
                        function_type_arguments)) {
      auto& name = String::Handle(zone, ParameterNameAt(param_index));
      if (!type.IsInstantiated()) {
        type =
            type.InstantiateFrom(instantiator_type_arguments,
                                 function_type_arguments, kAllFree, Heap::kNew);
      }
      return ThrowTypeError(token_pos(), argument, type, name);
    }
  }

  const intptr_t num_named_arguments = args_desc.NamedCount();
  if (num_named_arguments == 0) {
    return Error::null();
  }

  const int num_parameters = NumParameters();
  const int num_fixed_params = num_fixed_parameters();

  String& argument_name = String::Handle(zone);
  String& parameter_name = String::Handle(zone);

  // Check types of named arguments against expected parameter type.
  for (intptr_t named_index = 0; named_index < num_named_arguments;
       named_index++) {
    argument_name = args_desc.NameAt(named_index);
    ASSERT(argument_name.IsSymbol());
    argument ^= args.At(arg_offset + args_desc.PositionAt(named_index));

    // Try to find the named parameter that matches the provided argument.
    // Even when annotated with @required, named parameters are still stored
    // as if they were optional and so come after the fixed parameters.
    // Currently O(n^2) as there's no guarantee from either the CFE or the
    // VM that named parameters and named arguments are sorted in the same way.
    intptr_t param_index = num_fixed_params;
    for (; param_index < num_parameters; param_index++) {
      parameter_name = ParameterNameAt(param_index);
      ASSERT(parameter_name.IsSymbol());

      if (!parameter_name.Equals(argument_name)) continue;

      type = ParameterTypeAt(param_index);
      if (!check_argument(argument, type, instantiator_type_arguments,
                          function_type_arguments)) {
        auto& name = String::Handle(zone, ParameterNameAt(param_index));
        if (!type.IsInstantiated()) {
          type = type.InstantiateFrom(instantiator_type_arguments,
                                      function_type_arguments, kAllFree,
                                      Heap::kNew);
        }
        return ThrowTypeError(token_pos(), argument, type, name);
      }
      break;
    }
    // Only should fail if AreValidArguments returns a false positive.
    ASSERT(param_index < num_parameters);
  }
  return Error::null();
}

// Helper allocating a C string buffer in the zone, printing the fully qualified
// name of a function in it, and replacing ':' by '_' to make sure the
// constructed name is a valid C++ identifier for debugging purpose.
// Set 'chars' to allocated buffer and return number of written characters.

enum QualifiedFunctionLibKind {
  kQualifiedFunctionLibKindLibUrl,
  kQualifiedFunctionLibKindLibName
};

static intptr_t ConstructFunctionFullyQualifiedCString(
    const Function& function,
    char** chars,
    intptr_t reserve_len,
    bool with_lib,
    QualifiedFunctionLibKind lib_kind) {
  Zone* zone = Thread::Current()->zone();
  const char* name = String::Handle(zone, function.name()).ToCString();
  const char* function_format = (reserve_len == 0) ? "%s" : "%s_";
  reserve_len += Utils::SNPrint(nullptr, 0, function_format, name);
  const Function& parent = Function::Handle(zone, function.parent_function());
  intptr_t written = 0;
  if (parent.IsNull()) {
    const Class& function_class = Class::Handle(zone, function.Owner());
    ASSERT(!function_class.IsNull());
    const char* class_name =
        String::Handle(zone, function_class.Name()).ToCString();
    ASSERT(class_name != nullptr);
    const char* library_name = nullptr;
    const char* lib_class_format = nullptr;
    if (with_lib) {
      const Library& library = Library::Handle(zone, function_class.library());
      ASSERT(!library.IsNull());
      switch (lib_kind) {
        case kQualifiedFunctionLibKindLibUrl:
          library_name = String::Handle(zone, library.url()).ToCString();
          break;
        case kQualifiedFunctionLibKindLibName:
          library_name = String::Handle(zone, library.name()).ToCString();
          break;
        default:
          UNREACHABLE();
      }
      ASSERT(library_name != nullptr);
      lib_class_format = (library_name[0] == '\0') ? "%s%s_" : "%s_%s_";
    } else {
      library_name = "";
      lib_class_format = "%s%s.";
    }
    reserve_len +=
        Utils::SNPrint(nullptr, 0, lib_class_format, library_name, class_name);
    ASSERT(chars != nullptr);
    *chars = zone->Alloc<char>(reserve_len + 1);
    written = Utils::SNPrint(*chars, reserve_len + 1, lib_class_format,
                             library_name, class_name);
  } else {
    written = ConstructFunctionFullyQualifiedCString(parent, chars, reserve_len,
                                                     with_lib, lib_kind);
  }
  ASSERT(*chars != nullptr);
  char* next = *chars + written;
  written += Utils::SNPrint(next, reserve_len + 1, function_format, name);
  // Replace ":" with "_".
  while (true) {
    next = strchr(next, ':');
    if (next == nullptr) break;
    *next = '_';
  }
  return written;
}

const char* Function::ToFullyQualifiedCString() const {
  char* chars = nullptr;
  ConstructFunctionFullyQualifiedCString(*this, &chars, 0, true,
                                         kQualifiedFunctionLibKindLibUrl);
  return chars;
}

const char* Function::ToLibNamePrefixedQualifiedCString() const {
  char* chars = nullptr;
  ConstructFunctionFullyQualifiedCString(*this, &chars, 0, true,
                                         kQualifiedFunctionLibKindLibName);
  return chars;
}

const char* Function::ToQualifiedCString() const {
  char* chars = nullptr;
  ConstructFunctionFullyQualifiedCString(*this, &chars, 0, false,
                                         kQualifiedFunctionLibKindLibUrl);
  return chars;
}

AbstractTypePtr FunctionType::InstantiateFrom(
    const TypeArguments& instantiator_type_arguments,
    const TypeArguments& function_type_arguments,
    intptr_t num_free_fun_type_params,
    Heap::Space space,
    FunctionTypeMapping* function_type_mapping,
    intptr_t num_parent_type_args_adjustment) const {
  ASSERT(IsFinalized());
  Zone* zone = Thread::Current()->zone();
  const intptr_t num_parent_type_args = NumParentTypeArguments();
  bool delete_type_parameters = false;
  if (num_free_fun_type_params == kCurrentAndEnclosingFree) {
    // See the comment on kCurrentAndEnclosingFree to understand why we don't
    // adjust 'num_free_fun_type_params' downward in this case.
    num_free_fun_type_params = kAllFree;
    delete_type_parameters = true;
  } else {
    ASSERT(!IsInstantiated(kAny, num_free_fun_type_params));
    // We only consider the function type parameters declared by the parents
    // of this signature function as free.
    if (num_parent_type_args < num_free_fun_type_params) {
      num_free_fun_type_params = num_parent_type_args;
    }
  }

  // The number of parent type parameters that remain uninstantiated.
  const intptr_t remaining_parent_type_params =
      num_free_fun_type_params < num_parent_type_args
          ? num_parent_type_args - num_free_fun_type_params
          : 0;

  // Adjust number of parent type arguments for all nested substituted types.
  num_parent_type_args_adjustment =
      remaining_parent_type_params +
      (delete_type_parameters ? 0 : NumTypeParameters());

  FunctionType& sig = FunctionType::Handle(
      FunctionType::New(remaining_parent_type_params, nullability(), space));
  AbstractType& type = AbstractType::Handle(zone);

  FunctionTypeMapping scope(zone, &function_type_mapping, *this, sig);

  // Copy the type parameters and instantiate their bounds and defaults.
  if (!delete_type_parameters) {
    const TypeParameters& type_params =
        TypeParameters::Handle(zone, type_parameters());
    if (!type_params.IsNull()) {
      const TypeParameters& sig_type_params =
          TypeParameters::Handle(zone, TypeParameters::New());
      // No need to set names that are ignored in a signature, however, the
      // length of the names array defines the number of type parameters.
      sig_type_params.set_names(Array::Handle(zone, type_params.names()));
      sig_type_params.set_flags(Array::Handle(zone, type_params.flags()));
      sig.SetTypeParameters(sig_type_params);
      TypeArguments& type_args = TypeArguments::Handle(zone);
      type_args = type_params.bounds();
      if (!type_args.IsNull() && !type_args.IsInstantiated()) {
        type_args = type_args.InstantiateFrom(
            instantiator_type_arguments, function_type_arguments,
            num_free_fun_type_params, space, function_type_mapping,
            num_parent_type_args_adjustment);
      }
      sig_type_params.set_bounds(type_args);
      type_args = type_params.defaults();
      if (!type_args.IsNull() && !type_args.IsInstantiated()) {
        type_args = type_args.InstantiateFrom(
            instantiator_type_arguments, function_type_arguments,
            num_free_fun_type_params, space, function_type_mapping,
            num_parent_type_args_adjustment);
      }
      sig_type_params.set_defaults(type_args);
    }
  }

  type = result_type();
  if (!type.IsInstantiated()) {
    type = type.InstantiateFrom(
        instantiator_type_arguments, function_type_arguments,
        num_free_fun_type_params, space, function_type_mapping,
        num_parent_type_args_adjustment);
    // A returned null type indicates a failed instantiation in dead code that
    // must be propagated up to the caller, the optimizing compiler.
    if (type.IsNull()) {
      return FunctionType::null();
    }
  }
  sig.set_result_type(type);
  const intptr_t num_params = NumParameters();
  sig.set_num_implicit_parameters(num_implicit_parameters());
  sig.set_num_fixed_parameters(num_fixed_parameters());
  sig.SetNumOptionalParameters(NumOptionalParameters(),
                               HasOptionalPositionalParameters());
  sig.set_parameter_types(Array::Handle(Array::New(num_params, space)));
  for (intptr_t i = 0; i < num_params; i++) {
    type = ParameterTypeAt(i);
    if (!type.IsInstantiated()) {
      type = type.InstantiateFrom(
          instantiator_type_arguments, function_type_arguments,
          num_free_fun_type_params, space, function_type_mapping,
          num_parent_type_args_adjustment);
      // A returned null type indicates a failed instantiation in dead code that
      // must be propagated up to the caller, the optimizing compiler.
      if (type.IsNull()) {
        return FunctionType::null();
      }
    }
    sig.SetParameterTypeAt(i, type);
  }
  sig.set_named_parameter_names(Array::Handle(zone, named_parameter_names()));

  if (delete_type_parameters) {
    ASSERT(sig.IsInstantiated(kFunctions));
  }

  sig.SetIsFinalized();

  // Canonicalization is not part of instantiation.
  return sig.ptr();
}

AbstractTypePtr FunctionType::UpdateFunctionTypes(
    intptr_t num_parent_type_args_adjustment,
    intptr_t num_free_fun_type_params,
    Heap::Space space,
    FunctionTypeMapping* function_type_mapping) const {
  ASSERT(num_parent_type_args_adjustment >= 0);
  ASSERT(IsFinalized());
  Zone* zone = Thread::Current()->zone();

  const intptr_t old_num_parent_type_args = NumParentTypeArguments();
  // From now on, adjust all type parameter types
  // which belong to this or nested function types.
  if (num_free_fun_type_params > old_num_parent_type_args) {
    num_free_fun_type_params = old_num_parent_type_args;
  }

  FunctionType& new_type = FunctionType::Handle(
      zone, FunctionType::New(
                NumParentTypeArguments() + num_parent_type_args_adjustment,
                nullability(), space));
  AbstractType& type = AbstractType::Handle(zone);

  FunctionTypeMapping scope(zone, &function_type_mapping, *this, new_type);

  const TypeParameters& type_params =
      TypeParameters::Handle(zone, type_parameters());
  if (!type_params.IsNull()) {
    const TypeParameters& new_type_params =
        TypeParameters::Handle(zone, TypeParameters::New());
    // No need to set names that are ignored in a signature, however, the
    // length of the names array defines the number of type parameters.
    new_type_params.set_names(Array::Handle(zone, type_params.names()));
    new_type_params.set_flags(Array::Handle(zone, type_params.flags()));
    TypeArguments& type_args = TypeArguments::Handle(zone);
    type_args = type_params.bounds();
    if (!type_args.IsNull()) {
      type_args = type_args.UpdateFunctionTypes(num_parent_type_args_adjustment,
                                                num_free_fun_type_params, space,
                                                function_type_mapping);
    }
    new_type_params.set_bounds(type_args);
    type_args = type_params.defaults();
    if (!type_args.IsNull()) {
      type_args = type_args.UpdateFunctionTypes(num_parent_type_args_adjustment,
                                                num_free_fun_type_params, space,
                                                function_type_mapping);
    }
    new_type_params.set_defaults(type_args);
    new_type.SetTypeParameters(new_type_params);
  }

  type = result_type();
  type = type.UpdateFunctionTypes(num_parent_type_args_adjustment,
                                  num_free_fun_type_params, space,
                                  function_type_mapping);
  new_type.set_result_type(type);

  const intptr_t num_params = NumParameters();
  new_type.set_num_implicit_parameters(num_implicit_parameters());
  new_type.set_num_fixed_parameters(num_fixed_parameters());
  new_type.SetNumOptionalParameters(NumOptionalParameters(),
                                    HasOptionalPositionalParameters());
  new_type.set_parameter_types(Array::Handle(Array::New(num_params, space)));
  for (intptr_t i = 0; i < num_params; i++) {
    type = ParameterTypeAt(i);
    type = type.UpdateFunctionTypes(num_parent_type_args_adjustment,
                                    num_free_fun_type_params, space,
                                    function_type_mapping);
    new_type.SetParameterTypeAt(i, type);
  }
  new_type.set_named_parameter_names(
      Array::Handle(zone, named_parameter_names()));
  new_type.SetIsFinalized();

  return new_type.ptr();
}

// Checks if the type of the specified parameter of this signature is a
// supertype of the type of the specified parameter of the other signature
// (i.e. check parameter contravariance).
// Note that types marked as covariant are already dealt with in the front-end.
bool FunctionType::IsContravariantParameter(
    intptr_t parameter_position,
    const FunctionType& other,
    intptr_t other_parameter_position,
    Heap::Space space,
    FunctionTypeMapping* function_type_equivalence) const {
  const AbstractType& param_type =
      AbstractType::Handle(ParameterTypeAt(parameter_position));
  if (param_type.IsTopTypeForSubtyping()) {
    return true;
  }
  const AbstractType& other_param_type =
      AbstractType::Handle(other.ParameterTypeAt(other_parameter_position));
  return other_param_type.IsSubtypeOf(param_type, space,
                                      function_type_equivalence);
}

bool FunctionType::HasSameTypeParametersAndBounds(
    const FunctionType& other,
    TypeEquality kind,
    FunctionTypeMapping* function_type_equivalence) const {
  Zone* const zone = Thread::Current()->zone();
  TRACE_TYPE_CHECKS_VERBOSE(
      "  FunctionType::HasSameTypeParametersAndBounds(%s, %s)\n", ToCString(),
      other.ToCString());

  const intptr_t num_type_params = NumTypeParameters();
  if (num_type_params != other.NumTypeParameters()) {
    TRACE_TYPE_CHECKS_VERBOSE(
        "   - result: false (number of type parameters)\n");
    return false;
  }
  if (num_type_params > 0) {
    const TypeParameters& type_params =
        TypeParameters::Handle(zone, type_parameters());
    ASSERT(!type_params.IsNull());
    const TypeParameters& other_type_params =
        TypeParameters::Handle(zone, other.type_parameters());
    ASSERT(!other_type_params.IsNull());
    if (kind == TypeEquality::kInSubtypeTest) {
      if (!type_params.AllDynamicBounds() ||
          !other_type_params.AllDynamicBounds()) {
        AbstractType& bound = AbstractType::Handle(zone);
        AbstractType& other_bound = AbstractType::Handle(zone);
        for (intptr_t i = 0; i < num_type_params; i++) {
          bound = type_params.BoundAt(i);
          other_bound = other_type_params.BoundAt(i);
          // Bounds that are mutual subtypes are considered equal.
          if (!bound.IsSubtypeOf(other_bound, Heap::kOld,
                                 function_type_equivalence) ||
              !other_bound.IsSubtypeOf(bound, Heap::kOld,
                                       function_type_equivalence)) {
            TRACE_TYPE_CHECKS_VERBOSE(
                "   - result: false (bounds are not mutual subtypes)\n");
            return false;
          }
        }
      }
    } else {
      if (NumParentTypeArguments() != other.NumParentTypeArguments()) {
        TRACE_TYPE_CHECKS_VERBOSE(
            "   - result: false (mismatch in number of type arguments)\n");
        return false;
      }
      const TypeArguments& bounds =
          TypeArguments::Handle(zone, type_params.bounds());
      const TypeArguments& other_bounds =
          TypeArguments::Handle(zone, other_type_params.bounds());
      if (!bounds.IsEquivalent(other_bounds, kind, function_type_equivalence)) {
        TRACE_TYPE_CHECKS_VERBOSE(
            "   - result: false (bounds are not equivalent)\n");
        return false;
      }
      if (kind == TypeEquality::kCanonical) {
        // Compare default arguments.
        const TypeArguments& defaults =
            TypeArguments::Handle(zone, type_params.defaults());
        const TypeArguments& other_defaults =
            TypeArguments::Handle(zone, other_type_params.defaults());
        if (!defaults.IsEquivalent(other_defaults, kind,
                                   function_type_equivalence)) {
          TRACE_TYPE_CHECKS_VERBOSE(
              "   - result: false (default types are not equivalent,"
              " %s - %s)\n",
              defaults.ToCString(), other_defaults.ToCString());
          return false;
        }
      }
    }
    if (kind != TypeEquality::kInSubtypeTest) {
      // Compare flags (IsGenericCovariantImpl).
      if (!Array::Equals(type_params.flags(), other_type_params.flags())) {
        TRACE_TYPE_CHECKS_VERBOSE("   - result: false (flags are not equal)\n");
        return false;
      }
    }
  }
  TRACE_TYPE_CHECKS_VERBOSE("   - result: true\n");
  return true;
}

bool FunctionType::IsSubtypeOf(
    const FunctionType& other,
    Heap::Space space,
    FunctionTypeMapping* function_type_equivalence) const {
  TRACE_TYPE_CHECKS_VERBOSE("  FunctionType::IsSubtypeOf(%s, %s)\n",
                            ToCString(), other.ToCString());
  const intptr_t num_fixed_params = num_fixed_parameters();
  const intptr_t num_opt_pos_params = NumOptionalPositionalParameters();
  const intptr_t num_opt_named_params = NumOptionalNamedParameters();
  const intptr_t other_num_fixed_params = other.num_fixed_parameters();
  const intptr_t other_num_opt_pos_params =
      other.NumOptionalPositionalParameters();
  const intptr_t other_num_opt_named_params =
      other.NumOptionalNamedParameters();
  // This signature requires the same arguments or less and accepts the same
  // arguments or more. We can ignore implicit parameters.
  const intptr_t num_ignored_params = num_implicit_parameters();
  const intptr_t other_num_ignored_params = other.num_implicit_parameters();
  if (((num_fixed_params - num_ignored_params) >
       (other_num_fixed_params - other_num_ignored_params)) ||
      ((num_fixed_params - num_ignored_params + num_opt_pos_params) <
       (other_num_fixed_params - other_num_ignored_params +
        other_num_opt_pos_params)) ||
      (num_opt_named_params < other_num_opt_named_params)) {
    TRACE_TYPE_CHECKS_VERBOSE(
        "   - result: false (mismatch in number of parameters)\n");
    return false;
  }
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  FunctionTypeMapping scope(zone, &function_type_equivalence, *this, other);

  // Check the type parameters and bounds of generic functions.
  if (!HasSameTypeParametersAndBounds(other, TypeEquality::kInSubtypeTest,
                                      function_type_equivalence)) {
    TRACE_TYPE_CHECKS_VERBOSE(
        "   - result: false (mismatch in type parameters)\n");
    return false;
  }
  // Check the result type.
  const AbstractType& other_res_type =
      AbstractType::Handle(zone, other.result_type());
  // 'void Function()' is a subtype of 'Object Function()'.
  if (!other_res_type.IsTopTypeForSubtyping()) {
    const AbstractType& res_type = AbstractType::Handle(zone, result_type());
    if (!res_type.IsSubtypeOf(other_res_type, space,
                              function_type_equivalence)) {
      TRACE_TYPE_CHECKS_VERBOSE("   - result: false (result type)\n");
      return false;
    }
  }
  // Check the types of fixed and optional positional parameters.
  for (intptr_t i = 0; i < (other_num_fixed_params - other_num_ignored_params +
                            other_num_opt_pos_params);
       i++) {
    if (!IsContravariantParameter(i + num_ignored_params, other,
                                  i + other_num_ignored_params, space,
                                  function_type_equivalence)) {
      TRACE_TYPE_CHECKS_VERBOSE("   - result: false (parameter type)\n");
      return false;
    }
  }
  // Check that for each optional named parameter of type T of the other
  // function type, there exists an optional named parameter of this function
  // type with an identical name and with a type S that is a supertype of T.
  // Note that SetParameterNameAt() guarantees that names are symbols, so we
  // can compare their raw pointers.
  const int num_params = num_fixed_params + num_opt_named_params;
  const int other_num_params =
      other_num_fixed_params + other_num_opt_named_params;
  bool found_param_name;
  String& other_param_name = String::Handle(zone);
  for (intptr_t i = other_num_fixed_params; i < other_num_params; i++) {
    other_param_name = other.ParameterNameAt(i);
    ASSERT(other_param_name.IsSymbol());
    found_param_name = false;
    for (intptr_t j = num_fixed_params; j < num_params; j++) {
      ASSERT(String::Handle(zone, ParameterNameAt(j)).IsSymbol());
      if (ParameterNameAt(j) == other_param_name.ptr()) {
        found_param_name = true;
        if (!IsContravariantParameter(j, other, i, space,
                                      function_type_equivalence)) {
          TRACE_TYPE_CHECKS_VERBOSE(
              "   - result: false (optional parameter type)\n");
          return false;
        }
        break;
      }
    }
    if (!found_param_name) {
      TRACE_TYPE_CHECKS_VERBOSE(
          "   - result: false (named parameter not found)\n");
      return false;
    }
  }
  // Check that for each required named parameter in this function, there's a
  // corresponding required named parameter in the other function.
  String& param_name = other_param_name;
  for (intptr_t j = num_params - num_opt_named_params; j < num_params; j++) {
    if (IsRequiredAt(j)) {
      param_name = ParameterNameAt(j);
      ASSERT(param_name.IsSymbol());
      bool found = false;
      for (intptr_t i = other_num_fixed_params; i < other_num_params; i++) {
        ASSERT(String::Handle(zone, other.ParameterNameAt(i)).IsSymbol());
        if (other.ParameterNameAt(i) == param_name.ptr()) {
          found = true;
          if (!other.IsRequiredAt(i)) {
            TRACE_TYPE_CHECKS_VERBOSE(
                "   - result: false (mismatch in required named "
                "parameters)\n");
            return false;
          }
        }
      }
      if (!found) {
        TRACE_TYPE_CHECKS_VERBOSE(
            "   - result: false (required named parameter not found)\n");
        return false;
      }
    }
  }
  TRACE_TYPE_CHECKS_VERBOSE("   - result: true\n");
  return true;
}

// The compiler generates an implicit constructor if a class definition
// does not contain an explicit constructor or factory. The implicit
// constructor has the same token position as the owner class.
bool Function::IsImplicitConstructor() const {
  return IsGenerativeConstructor() && (token_pos() == end_token_pos());
}

bool Function::IsImplicitStaticClosureFunction(FunctionPtr func) {
  NoSafepointScope no_safepoint;
  uint32_t kind_tag = func->untag()->kind_tag_.load(std::memory_order_relaxed);
  return (KindBits::decode(kind_tag) ==
          UntaggedFunction::kImplicitClosureFunction) &&
         StaticBit::decode(kind_tag);
}

bool Function::IsImplicitInstanceClosureFunction(FunctionPtr func) {
  NoSafepointScope no_safepoint;
  uint32_t kind_tag = func->untag()->kind_tag_.load(std::memory_order_relaxed);
  return (KindBits::decode(kind_tag) ==
          UntaggedFunction::kImplicitClosureFunction) &&
         !StaticBit::decode(kind_tag);
}

FunctionPtr Function::New(Heap::Space space) {
  ASSERT(Object::function_class() != Class::null());
  return Object::Allocate<Function>(space);
}

FunctionPtr Function::New(const FunctionType& signature,
                          const String& name,
                          UntaggedFunction::Kind kind,
                          bool is_static,
                          bool is_const,
                          bool is_abstract,
                          bool is_external,
                          bool is_native,
                          const Object& owner,
                          TokenPosition token_pos,
                          Heap::Space space) {
  ASSERT(!owner.IsNull());
  ASSERT(!signature.IsNull());
  const Function& result = Function::Handle(Function::New(space));
  result.set_kind_tag(0);
  result.set_name(name);
  result.set_kind_tag(0);  // Ensure determinism of uninitialized bits.
  result.set_kind(kind);
  result.set_recognized_kind(MethodRecognizer::kUnknown);
  result.set_modifier(UntaggedFunction::kNoModifier);
  result.set_is_static(is_static);
  result.set_is_const(is_const);
  result.set_is_abstract(is_abstract);
  result.set_is_external(is_external);
  result.set_is_native(is_native);
  result.set_is_reflectable(true);  // Will be computed later.
  result.set_is_visible(true);      // Will be computed later.
  result.set_is_debuggable(true);   // Will be computed later.
  result.set_is_intrinsic(false);
  result.set_has_pragma(false);
  result.set_is_polymorphic_target(false);
  result.set_is_synthetic(false);
  NOT_IN_PRECOMPILED(result.set_state_bits(0));
  result.set_owner(owner);
  NOT_IN_PRECOMPILED(result.set_token_pos(token_pos));
  NOT_IN_PRECOMPILED(result.set_end_token_pos(token_pos));
  NOT_IN_PRECOMPILED(result.set_usage_counter(0));
  NOT_IN_PRECOMPILED(result.set_deoptimization_counter(0));
  NOT_IN_PRECOMPILED(result.set_optimized_instruction_count(0));
  NOT_IN_PRECOMPILED(result.set_optimized_call_site_count(0));
  NOT_IN_PRECOMPILED(result.set_inlining_depth(0));
  NOT_IN_PRECOMPILED(result.set_kernel_offset(0));
  NOT_IN_PRECOMPILED(result.set_is_optimizable(is_native ? false : true));
  result.set_is_inlinable(true);
  result.reset_unboxed_parameters_and_return();
  result.SetInstructionsSafe(StubCode::LazyCompile());

  // See Function::set_data() for more information.
  if (kind == UntaggedFunction::kClosureFunction ||
      kind == UntaggedFunction::kImplicitClosureFunction) {
    ASSERT(space == Heap::kOld);
    const ClosureData& data = ClosureData::Handle(ClosureData::New());
    data.set_awaiter_link({});
    result.set_data(data);
  } else if (kind == UntaggedFunction::kFfiTrampoline) {
    const FfiTrampolineData& data =
        FfiTrampolineData::Handle(FfiTrampolineData::New());
    result.set_data(data);
  } else if (result.is_old_native()) {
    const auto& data =
        Array::Handle(Array::New(NativeFunctionData::kLength, Heap::kOld));
    result.set_data(data);
  } else {
    // Functions other than signature functions have no reason to be allocated
    // in new space.
    ASSERT(space == Heap::kOld);
  }

  // Force-optimized functions are not debuggable because they cannot
  // deoptimize.
  if (result.ForceOptimize()) {
    result.set_is_debuggable(false);
  }
  signature.set_num_implicit_parameters(result.NumImplicitParameters());
  result.SetSignature(signature);
  NOT_IN_PRECOMPILED(
      result.set_positional_parameter_names(Object::empty_array()));
  return result.ptr();
}

FunctionPtr Function::NewClosureFunctionWithKind(UntaggedFunction::Kind kind,
                                                 const String& name,
                                                 const Function& parent,
                                                 bool is_static,
                                                 TokenPosition token_pos,
                                                 const Object& owner) {
  ASSERT((kind == UntaggedFunction::kClosureFunction) ||
         (kind == UntaggedFunction::kImplicitClosureFunction));
  ASSERT(!parent.IsNull());
  ASSERT(!owner.IsNull());
  const FunctionType& signature = FunctionType::Handle(FunctionType::New(
      kind == UntaggedFunction::kClosureFunction ? parent.NumTypeArguments()
                                                 : 0));
  const Function& result = Function::Handle(
      Function::New(signature, name, kind,
                    /* is_static = */ is_static,
                    /* is_const = */ false,
                    /* is_abstract = */ false,
                    /* is_external = */ false,
                    /* is_native = */ false, owner, token_pos));
  result.set_parent_function(parent);
  return result.ptr();
}

FunctionPtr Function::NewClosureFunction(const String& name,
                                         const Function& parent,
                                         TokenPosition token_pos) {
  // Use the owner defining the parent function and not the class containing it.
  const Object& parent_owner = Object::Handle(parent.RawOwner());
  return NewClosureFunctionWithKind(UntaggedFunction::kClosureFunction, name,
                                    parent, parent.is_static(), token_pos,
                                    parent_owner);
}

FunctionPtr Function::NewImplicitClosureFunction(const String& name,
                                                 const Function& parent,
                                                 TokenPosition token_pos) {
  // Use the owner defining the parent function and not the class containing it.
  const Object& parent_owner = Object::Handle(parent.RawOwner());
  return NewClosureFunctionWithKind(
      UntaggedFunction::kImplicitClosureFunction, name, parent,
      parent.is_static() || parent.IsConstructor(), token_pos, parent_owner);
}

bool Function::SafeToClosurize() const {
#if defined(DART_PRECOMPILED_RUNTIME)
  return HasImplicitClosureFunction();
#else
  return true;
#endif
}

bool Function::IsDynamicClosureCallDispatcher() const {
  if (!IsInvokeFieldDispatcher()) return false;
  if (!Class::IsClosureClass(Owner())) return false;
  return name() == Symbols::DynamicCall().ptr();
}

bool Function::IsClosureCallDispatcher() const {
  if (!IsInvokeFieldDispatcher()) return false;
  if (!Class::IsClosureClass(Owner())) return false;
  return name() == Symbols::call().ptr();
}

FunctionPtr Function::ImplicitClosureFunction() const {
  // Return the existing implicit closure function if any.
  if (implicit_closure_function() != Function::null()) {
    return implicit_closure_function();
  }

#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES)
  // In AOT mode all implicit closures are pre-created.
  FATAL("Cannot create implicit closure in AOT!");
  return Function::null();
#else
  ASSERT(!IsClosureFunction());
  Thread* thread = Thread::Current();
  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());

  if (implicit_closure_function() != Function::null()) {
    return implicit_closure_function();
  }

  // Create closure function.
  Zone* zone = thread->zone();
  const String& closure_name = String::Handle(zone, name());
  const Function& closure_function = Function::Handle(
      zone, NewImplicitClosureFunction(closure_name, *this, token_pos()));

  // Set closure function's context scope.
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (is_static() || IsConstructor()) {
    closure_function.set_context_scope(Object::empty_context_scope());
  } else {
    const ContextScope& context_scope = ContextScope::Handle(
        zone, LocalScope::CreateImplicitClosureScope(*this));
    closure_function.set_context_scope(context_scope);
  }
#endif

  FunctionType& closure_signature =
      FunctionType::Handle(zone, closure_function.signature());

  const auto& cls = Class::Handle(zone, Owner());

  if (!is_static() && !IsConstructor() &&
      StackTraceUtils::IsPossibleAwaiterLink(cls)) {
    closure_function.set_awaiter_link({0, 0});
  }

  const intptr_t num_type_params =
      IsConstructor() ? cls.NumTypeParameters() : NumTypeParameters();

  TypeArguments& instantiator_type_arguments = TypeArguments::Handle(zone);
  TypeArguments& function_type_arguments = TypeArguments::Handle(zone);

  FunctionTypeMapping* function_type_mapping = nullptr;
  FunctionTypeMapping scope(zone, &function_type_mapping,
                            FunctionType::Handle(zone, signature()),
                            closure_signature);

  auto transform_type = [&](AbstractType& type) {
    if (num_type_params > 0) {
      if (IsConstructor()) {
        type = type.UpdateFunctionTypes(num_type_params, kAllFree, Heap::kOld,
                                        nullptr);
        if (!type.IsInstantiated(kCurrentClass)) {
          type = type.InstantiateFrom(
              instantiator_type_arguments, function_type_arguments,
              kNoneFree /* avoid truncating parent type args */, Heap::kOld);
        }
      } else {
        type = type.UpdateFunctionTypes(0, kNoneFree, Heap::kOld,
                                        function_type_mapping);
      }
    }
  };

  auto transform_type_args = [&](TypeArguments& type_args) {
    ASSERT(num_type_params > 0);
    if (!type_args.IsNull()) {
      if (IsConstructor()) {
        type_args = type_args.UpdateFunctionTypes(num_type_params, kAllFree,
                                                  Heap::kOld, nullptr);
        if (!type_args.IsInstantiated(kCurrentClass)) {
          type_args = type_args.InstantiateFrom(
              instantiator_type_arguments, function_type_arguments,
              kNoneFree /* avoid truncating parent type args */, Heap::kOld);
        }
      } else {
        type_args = type_args.UpdateFunctionTypes(0, kNoneFree, Heap::kOld,
                                                  function_type_mapping);
      }
    }
  };

  // Set closure function's type parameters.
  if (num_type_params > 0) {
    const TypeParameters& old_type_params = TypeParameters::Handle(
        zone, IsConstructor() ? cls.type_parameters() : type_parameters());
    const TypeParameters& new_type_params =
        TypeParameters::Handle(zone, TypeParameters::New());
    // No need to set names that are ignored in a signature, however, the
    // length of the names array defines the number of type parameters.
    new_type_params.set_names(Array::Handle(zone, old_type_params.names()));
    new_type_params.set_flags(Array::Handle(zone, old_type_params.flags()));

    closure_signature.SetTypeParameters(new_type_params);
    ASSERT(closure_signature.NumTypeParameters() == num_type_params);

    TypeArguments& type_args = TypeArguments::Handle(zone);
    type_args = TypeArguments::New(num_type_params);
    TypeParameter& type_param = TypeParameter::Handle(zone);
    for (intptr_t i = 0; i < num_type_params; i++) {
      type_param = closure_signature.TypeParameterAt(i);
      type_args.SetTypeAt(i, type_param);
    }

    if (IsConstructor()) {
      instantiator_type_arguments =
          type_args.ToInstantiatorTypeArguments(thread, cls);
    } else {
      ASSERT(NumTypeArguments() == type_args.Length());
      function_type_arguments = type_args.ptr();
    }

    type_args = old_type_params.bounds();
    transform_type_args(type_args);
    new_type_params.set_bounds(type_args);

    type_args = old_type_params.defaults();
    transform_type_args(type_args);
    new_type_params.set_defaults(type_args);
  }

  // Set closure function's result type.
  AbstractType& result_type = AbstractType::Handle(zone);
  if (IsConstructor()) {
    result_type = cls.DeclarationType();
  } else {
    result_type = this->result_type();
  }
  transform_type(result_type);
  closure_signature.set_result_type(result_type);

  // Set closure function's end token to this end token.
  NOT_IN_PRECOMPILED(closure_function.set_end_token_pos(end_token_pos()));

  // The closurized method stub just calls into the original method and should
  // therefore be skipped by the debugger and in stack traces.
  closure_function.set_is_debuggable(false);
  closure_function.set_is_visible(false);

  // Set closure function's formal parameters to this formal parameters,
  // removing the receiver if this is an instance method and adding the closure
  // object as first parameter.
  const int kClosure = 1;
  const int num_implicit_params = NumImplicitParameters();
  const int num_fixed_params =
      kClosure - num_implicit_params + num_fixed_parameters();
  const int num_opt_params = NumOptionalParameters();
  const bool has_opt_pos_params = HasOptionalPositionalParameters();
  const int num_params = num_fixed_params + num_opt_params;
  const int num_pos_params = has_opt_pos_params ? num_params : num_fixed_params;
  closure_signature.set_num_fixed_parameters(num_fixed_params);
  closure_signature.SetNumOptionalParameters(num_opt_params,
                                             has_opt_pos_params);
  closure_signature.set_parameter_types(
      Array::Handle(zone, Array::New(num_params, Heap::kOld)));
  NOT_IN_PRECOMPILED(closure_function.CreateNameArray());
  closure_signature.CreateNameArrayIncludingFlags();
  AbstractType& param_type = AbstractType::Handle(zone);
  String& param_name = String::Handle(zone);
  // Add implicit closure object parameter.
  param_type = Type::DynamicType();
  closure_signature.SetParameterTypeAt(0, param_type);
  NOT_IN_PRECOMPILED(
      closure_function.SetParameterNameAt(0, Symbols::ClosureParameter()));
  for (int i = kClosure; i < num_pos_params; i++) {
    param_type = ParameterTypeAt(num_implicit_params - kClosure + i);
    transform_type(param_type);
    closure_signature.SetParameterTypeAt(i, param_type);
    param_name = ParameterNameAt(num_implicit_params - kClosure + i);
    // Set the name in the function for positional parameters.
    NOT_IN_PRECOMPILED(closure_function.SetParameterNameAt(i, param_name));
  }
  for (int i = num_pos_params; i < num_params; i++) {
    param_type = ParameterTypeAt(num_implicit_params - kClosure + i);
    transform_type(param_type);
    closure_signature.SetParameterTypeAt(i, param_type);
    param_name = ParameterNameAt(num_implicit_params - kClosure + i);
    // Set the name in the signature for named parameters.
    closure_signature.SetParameterNameAt(i, param_name);
    if (IsRequiredAt(num_implicit_params - kClosure + i)) {
      closure_signature.SetIsRequiredAt(i);
    }
  }
  closure_signature.FinalizeNameArray();
  closure_function.InheritKernelOffsetFrom(*this);

  if (!is_static() && !IsConstructor()) {
    // Change covariant parameter types to Object?.
    BitVector is_covariant(zone, NumParameters());
    BitVector is_generic_covariant_impl(zone, NumParameters());
    ReadParameterCovariance(&is_covariant, &is_generic_covariant_impl);

    ObjectStore* object_store = IsolateGroup::Current()->object_store();
    const auto& object_type =
        Type::Handle(zone, object_store->nullable_object_type());
    ASSERT(object_type.IsCanonical());
    for (intptr_t i = kClosure; i < num_params; ++i) {
      const intptr_t original_param_index = num_implicit_params - kClosure + i;
      if (is_covariant.Contains(original_param_index) ||
          is_generic_covariant_impl.Contains(original_param_index)) {
        closure_signature.SetParameterTypeAt(i, object_type);
      }
    }
  }

#if defined(DART_DYNAMIC_MODULES)
#if defined(DART_PRECOMPILED_RUNTIME)
  const bool attach_bytecode = true;
#else
  const bool attach_bytecode = is_declared_in_bytecode();
#endif
  if (attach_bytecode) {
    if (is_static()) {
      closure_function.AttachBytecode(
          Object::implicit_static_closure_bytecode());
    } else if (IsConstructor()) {
      closure_function.AttachBytecode(
          Object::implicit_constructor_closure_bytecode());
    } else {
      closure_function.AttachBytecode(
          Object::implicit_instance_closure_bytecode());
    }
  }
#endif

  ASSERT(!closure_signature.IsFinalized());
  closure_signature ^= ClassFinalizer::FinalizeType(closure_signature);
  closure_function.SetSignature(closure_signature);
  set_implicit_closure_function(closure_function);
  ASSERT(closure_function.IsImplicitClosureFunction());
  ASSERT(HasImplicitClosureFunction());
  return closure_function.ptr();
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

void Function::DropUncompiledImplicitClosureFunction() const {
  if (implicit_closure_function() != Function::null()) {
    const Function& func = Function::Handle(implicit_closure_function());
    if (!func.HasCode()) {
      set_implicit_closure_function(Function::Handle());
    }
  }
}

StringPtr Function::InternalSignature() const {
#if defined(DART_PRECOMPILED_RUNTIME)
  if (signature() == FunctionType::null()) {
    return String::null();
  }
#endif
  Thread* thread = Thread::Current();
  ZoneTextBuffer printer(thread->zone());
  const FunctionType& sig = FunctionType::Handle(signature());
  sig.Print(kInternalName, &printer);
  return Symbols::New(thread, printer.buffer());
}

StringPtr Function::UserVisibleSignature() const {
#if defined(DART_PRECOMPILED_RUNTIME)
  if (signature() == FunctionType::null()) {
    return String::null();
  }
#endif
  Thread* thread = Thread::Current();
  ZoneTextBuffer printer(thread->zone());
  const FunctionType& sig = FunctionType::Handle(signature());
  sig.Print(kUserVisibleName, &printer);
  return Symbols::New(thread, printer.buffer());
}

void FunctionType::PrintParameters(Thread* thread,
                                   Zone* zone,
                                   NameVisibility name_visibility,
                                   BaseTextBuffer* printer) const {
  AbstractType& param_type = AbstractType::Handle(zone);
  const intptr_t num_params = NumParameters();
  const intptr_t num_fixed_params = num_fixed_parameters();
  const intptr_t num_opt_pos_params = NumOptionalPositionalParameters();
  const intptr_t num_opt_named_params = NumOptionalNamedParameters();
  const intptr_t num_opt_params = num_opt_pos_params + num_opt_named_params;
  ASSERT((num_fixed_params + num_opt_params) == num_params);
  intptr_t i = 0;
  if (name_visibility == kUserVisibleName) {
    // Hide implicit parameters.
    i = num_implicit_parameters();
  }
  String& name = String::Handle(zone);
  while (i < num_fixed_params) {
    param_type = ParameterTypeAt(i);
    ASSERT(!param_type.IsNull());
    param_type.PrintName(name_visibility, printer);
    if (i != (num_params - 1)) {
      printer->AddString(", ");
    }
    i++;
  }
  if (num_opt_params > 0) {
    if (num_opt_pos_params > 0) {
      printer->AddString("[");
    } else {
      printer->AddString("{");
    }
    for (intptr_t i = num_fixed_params; i < num_params; i++) {
      if (num_opt_named_params > 0 && IsRequiredAt(i)) {
        printer->AddString("required ");
      }
      param_type = ParameterTypeAt(i);
      ASSERT(!param_type.IsNull());
      param_type.PrintName(name_visibility, printer);
      // The parameter name of an optional positional parameter does not need
      // to be part of the signature, since it is not used.
      if (num_opt_named_params > 0) {
        name = ParameterNameAt(i);
        printer->AddString(" ");
        printer->AddString(name.ToCString());
      }
      if (i != (num_params - 1)) {
        printer->AddString(", ");
      }
    }
    if (num_opt_pos_params > 0) {
      printer->AddString("]");
    } else {
      printer->AddString("}");
    }
  }
}

ClosurePtr Function::ImplicitStaticClosure() const {
  ASSERT(IsImplicitStaticClosureFunction());
  if (implicit_static_closure() != Closure::null()) {
    return implicit_static_closure();
  }

  auto thread = Thread::Current();
  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());

  if (implicit_static_closure() != Closure::null()) {
    return implicit_static_closure();
  }

  Zone* zone = thread->zone();
  const auto& closure =
      Closure::Handle(zone, Closure::New(Object::null_type_arguments(),
                                         Object::null_type_arguments(), *this,
                                         Object::null_object(), Heap::kOld));
  set_implicit_static_closure(closure);
  return implicit_static_closure();
}

ClosurePtr Function::ImplicitInstanceClosure(const Instance& receiver) const {
  ASSERT(IsImplicitClosureFunction());
  Zone* zone = Thread::Current()->zone();
  TypeArguments& instantiator_type_arguments = TypeArguments::Handle(zone);
  if (!HasInstantiatedSignature(kCurrentClass)) {
    instantiator_type_arguments = receiver.GetTypeArguments();
  }
  ASSERT(!HasGenericParent());  // No generic parent function.
  return Closure::New(instantiator_type_arguments,
                      Object::null_type_arguments(), *this, receiver);
}

FunctionPtr Function::ImplicitClosureTarget(Zone* zone) const {
  const auto& parent = Function::Handle(zone, parent_function());
  const auto& func_name = String::Handle(zone, parent.name());
  const auto& owner = Class::Handle(zone, parent.Owner());
  Thread* thread = Thread::Current();
  const auto& error = owner.EnsureIsFinalized(thread);
  ASSERT(error == Error::null());
  auto& target =
      Function::Handle(zone, Resolver::ResolveFunction(zone, owner, func_name));

  if (!target.IsNull() && (target.ptr() != parent.ptr())) {
    DEBUG_ASSERT(IsolateGroup::Current()->HasAttemptedReload());
    if ((target.is_static() != parent.is_static()) ||
        (target.kind() != parent.kind())) {
      target = Function::null();
    }
  }

  return target.ptr();
}

void FunctionType::Print(NameVisibility name_visibility,
                         BaseTextBuffer* printer) const {
  if (IsNull()) {
    printer->AddString("null");  // Signature optimized out in precompiler.
    return;
  }
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const TypeParameters& type_params =
      TypeParameters::Handle(zone, type_parameters());
  if (!type_params.IsNull()) {
    printer->AddString("<");
    const intptr_t base = NumParentTypeArguments();
    const bool kIsClassTypeParameter = false;
    // Type parameter names are meaningless after canonicalization.
    type_params.Print(thread, zone, kIsClassTypeParameter, base,
                      name_visibility, printer);
    printer->AddString(">");
  }
  printer->AddString("(");
  PrintParameters(thread, zone, name_visibility, printer);
  printer->AddString(") => ");
  const AbstractType& res_type = AbstractType::Handle(zone, result_type());
  if (!res_type.IsNull()) {
    res_type.PrintName(name_visibility, printer);
  } else {
    printer->AddString("null");
  }
}

bool Function::HasInstantiatedSignature(
    Genericity genericity,
    intptr_t num_free_fun_type_params) const {
  return FunctionType::Handle(signature())
      .IsInstantiated(genericity, num_free_fun_type_params);
}

bool FunctionType::IsInstantiated(Genericity genericity,
                                  intptr_t num_free_fun_type_params) const {
  if (num_free_fun_type_params == kCurrentAndEnclosingFree) {
    num_free_fun_type_params = kAllFree;
  } else if (genericity != kCurrentClass) {
    const intptr_t num_parent_type_args = NumParentTypeArguments();
    if (num_parent_type_args > 0 && num_free_fun_type_params > 0) {
      // The number of parent type arguments is cached in the FunctionType, so
      // we can't consider any FunctionType with free parent type arguments as
      // fully instantiated. Instead, the FunctionType must be instantiated to
      // reduce the number of parent type arguments, even if they're unused in
      // its component types.
      return false;
    }
    // Don't consider local function type parameters as free.
    if (num_free_fun_type_params > num_parent_type_args) {
      num_free_fun_type_params = num_parent_type_args;
    }
  }
  AbstractType& type = AbstractType::Handle(result_type());
  if (!type.IsInstantiated(genericity, num_free_fun_type_params)) {
    return false;
  }
  const intptr_t num_parameters = NumParameters();
  for (intptr_t i = 0; i < num_parameters; i++) {
    type = ParameterTypeAt(i);
    if (!type.IsInstantiated(genericity, num_free_fun_type_params)) {
      return false;
    }
  }
  const intptr_t num_type_params = NumTypeParameters();
  if (num_type_params > 0) {
    TypeParameters& type_params = TypeParameters::Handle(type_parameters());
    if (!type_params.AllDynamicBounds()) {
      for (intptr_t i = 0; i < type_params.Length(); ++i) {
        type = type_params.BoundAt(i);
        if (!type.IsInstantiated(genericity, num_free_fun_type_params)) {
          return false;
        }
      }
    }
  }
  return true;
}

bool Function::IsPrivate() const {
  return Library::IsPrivate(String::Handle(name()));
}

ClassPtr Function::Owner(FunctionPtr function) {
  ObjectPtr owner = function->untag()->owner();
  ASSERT(owner != Object::null());
  if (owner->IsClass()) {
    return Class::RawCast(owner);
  }
  ASSERT(owner->IsPatchClass());
  return PatchClass::RawCast(owner)->untag()->wrapped_class();
}

#if defined(DART_DYNAMIC_MODULES)
bool Function::is_declared_in_bytecode() const {
  return Class::Handle(Owner()).is_declared_in_bytecode();
}
#endif

void Function::InheritKernelOffsetFrom(const Function& src) const {
#if defined(DART_PRECOMPILED_RUNTIME)
#if !defined(DART_DYNAMIC_MODULES)
  UNREACHABLE();
#endif
#else
  StoreNonPointer(&untag()->kernel_offset_, src.untag()->kernel_offset_);
#endif
}

void Function::InheritKernelOffsetFrom(const Field& src) const {
#if defined(DART_PRECOMPILED_RUNTIME)
#if !defined(DART_DYNAMIC_MODULES)
  UNREACHABLE();
#endif
#else
  set_kernel_offset(src.kernel_offset());
#endif
}

void Function::SetKernelLibraryAndEvalScript(
    const Script& script,
    const class KernelProgramInfo& kernel_program_info,
    intptr_t index) const {
  Array& data_field = Array::Handle(
      Array::New(static_cast<intptr_t>(EvalFunctionData::kLength)));
  data_field.SetAt(static_cast<intptr_t>(EvalFunctionData::kScript), script);
  data_field.SetAt(static_cast<intptr_t>(EvalFunctionData::kKernelProgramInfo),
                   kernel_program_info);
  data_field.SetAt(static_cast<intptr_t>(EvalFunctionData::kKernelLibraryIndex),
                   Smi::Handle(Smi::New(index)));
  set_data(data_field);
}

ScriptPtr Function::script() const {
  // NOTE(turnidge): If you update this function, you probably want to
  // update Class::PatchFieldsAndFunctions() at the same time.
  if (IsDynamicInvocationForwarder()) {
    const Function& target = Function::Handle(ForwardingTarget());
    return target.IsNull() ? Script::null() : target.script();
  }
  if (IsImplicitGetterOrSetter()) {
    const auto& field = Field::Handle(accessor_field());
    return field.IsNull() ? Script::null() : field.Script();
  }
  if (is_eval_function()) {
    const auto& fdata = Array::Handle(Array::RawCast(data()));
    return Script::RawCast(
        fdata.At(static_cast<intptr_t>(EvalFunctionData::kScript)));
  }
  if (token_pos() == TokenPosition::kMinSource) {
    // Testing for position 0 is an optimization that relies on temporary
    // eval functions having token position 0.
    const Script& script = Script::Handle(eval_script());
    if (!script.IsNull()) {
      return script.ptr();
    }
  }
  const Object& obj = Object::Handle(untag()->owner());
  if (obj.IsPatchClass()) {
    return PatchClass::Cast(obj).script();
  }
  if (IsClosureFunction()) {
    const Function& function = Function::Handle(parent_function());
    if (function.IsNull()) return Script::null();
    return function.script();
  }
  ASSERT(obj.IsClass());
  return Class::Cast(obj).script();
}

#if !defined(DART_PRECOMPILED_RUNTIME)
KernelProgramInfoPtr Function::KernelProgramInfo() const {
  if (is_eval_function()) {
    const auto& fdata = Array::Handle(Array::RawCast(data()));
    return KernelProgramInfo::RawCast(
        fdata.At(static_cast<intptr_t>(EvalFunctionData::kKernelProgramInfo)));
  }
  if (IsClosureFunction()) {
    const auto& parent = Function::Handle(parent_function());
    return parent.KernelProgramInfo();
  }
  const auto& owner = Object::Handle(RawOwner());
  if (owner.IsClass()) {
    return Class::Cast(owner).KernelProgramInfo();
  }
  return PatchClass::Cast(owner).kernel_program_info();
}

TypedDataViewPtr Function::KernelLibrary() const {
  const intptr_t kernel_library_index = KernelLibraryIndex();
  if (kernel_library_index == -1) return TypedDataView::null();
  const auto& info = KernelProgramInfo::Handle(KernelProgramInfo());
  return info.KernelLibrary(kernel_library_index);
}

intptr_t Function::KernelLibraryOffset() const {
  const intptr_t kernel_library_index = KernelLibraryIndex();
  if (kernel_library_index == -1) return 0;
  const auto& info = KernelProgramInfo::Handle(KernelProgramInfo());
  return info.KernelLibraryStartOffset(kernel_library_index);
}

intptr_t Function::KernelLibraryIndex() const {
  ASSERT(!is_declared_in_bytecode());
  if (IsNoSuchMethodDispatcher() || IsInvokeFieldDispatcher() ||
      IsFfiCallbackTrampoline()) {
    return -1;
  }
  if (is_eval_function()) {
    const auto& fdata = Array::Handle(Array::RawCast(data()));
    return Smi::Value(static_cast<SmiPtr>(fdata.At(
        static_cast<intptr_t>(EvalFunctionData::kKernelLibraryIndex))));
  }
  if (IsClosureFunction()) {
    const auto& parent = Function::Handle(parent_function());
    ASSERT(!parent.IsNull());
    return parent.KernelLibraryIndex();
  }

  const auto& obj = Object::Handle(untag()->owner());
  if (obj.IsClass()) {
    const auto& lib = Library::Handle(Class::Cast(obj).library());
    return lib.kernel_library_index();
  }
  ASSERT(obj.IsPatchClass());
  return PatchClass::Cast(obj).kernel_library_index();
}
#endif

bool Function::HasOptimizedCode() const {
  return HasCode() && Code::Handle(CurrentCode()).is_optimized();
}

const char* Function::NameCString(NameVisibility name_visibility) const {
  switch (name_visibility) {
    case kInternalName:
      return String::Handle(name()).ToCString();
    case kScrubbedName:
    case kUserVisibleName:
      return UserVisibleNameCString();
  }
  UNREACHABLE();
  return nullptr;
}

const char* Function::UserVisibleNameCString() const {
  if (FLAG_show_internal_names) {
    return String::Handle(name()).ToCString();
  }
  is_extension_type_member();
  return String::ScrubName(String::Handle(name()),
                           is_extension_member() || is_extension_type_member());
}

StringPtr Function::UserVisibleName() const {
  if (FLAG_show_internal_names) {
    return name();
  }
  return Symbols::New(
      Thread::Current(),
      String::ScrubName(String::Handle(name()),
                        is_extension_member() || is_extension_type_member()));
}

StringPtr Function::QualifiedScrubbedName() const {
  Thread* thread = Thread::Current();
  ZoneTextBuffer printer(thread->zone());
  PrintName(NameFormattingParams(kScrubbedName), &printer);
  return Symbols::New(thread, printer.buffer());
}

const char* Function::QualifiedScrubbedNameCString() const {
  Thread* thread = Thread::Current();
  ZoneTextBuffer printer(thread->zone());
  PrintName(NameFormattingParams(kScrubbedName), &printer);
  return printer.buffer();
}

StringPtr Function::QualifiedUserVisibleName() const {
  Thread* thread = Thread::Current();
  ZoneTextBuffer printer(thread->zone());
  PrintName(NameFormattingParams(kUserVisibleName), &printer);
  return Symbols::New(thread, printer.buffer());
}

const char* Function::QualifiedUserVisibleNameCString() const {
  Thread* thread = Thread::Current();
  ZoneTextBuffer printer(thread->zone());
  PrintName(NameFormattingParams(kUserVisibleName), &printer);
  return printer.buffer();
}

static void FunctionPrintNameHelper(const Function& fun,
                                    const NameFormattingParams& params,
                                    BaseTextBuffer* printer) {
  if (fun.IsNonImplicitClosureFunction()) {
    if (params.include_parent_name) {
      const auto& parent = Function::Handle(fun.parent_function());
      if (parent.IsNull()) {
        printer->AddString(Symbols::OptimizedOut().ToCString());
      } else {
        parent.PrintName(params, printer);
      }
      // A function's scrubbed name and its user visible name are identical.
      printer->AddString(".");
    }
    if (params.disambiguate_names &&
        fun.name() == Symbols::AnonymousClosure().ptr()) {
      if (fun.token_pos().IsReal()) {
        printer->Printf("<anonymous closure @%" Pd ">", fun.token_pos().Pos());
      } else {
        printer->Printf("<anonymous closure @no position>");
      }
    } else {
      printer->AddString(fun.NameCString(params.name_visibility));
      if (params.disambiguate_names) {
        if (fun.token_pos().IsReal()) {
          printer->Printf("@<%" Pd ">", fun.token_pos().Pos());
        } else {
          printer->Printf("@<no position>");
        }
      }
    }
    return;
  }
  if (params.disambiguate_names) {
    if (fun.IsInvokeFieldDispatcher()) {
      printer->AddString("[invoke-field] ");
    }
    if (fun.IsNoSuchMethodDispatcher()) {
      printer->AddString("[no-such-method] ");
    }
    if (fun.IsImplicitClosureFunction()) {
      printer->AddString("[tear-off] ");
    }
    if (fun.IsMethodExtractor()) {
      printer->AddString("[tear-off-extractor] ");
    }
  }

  if (fun.kind() == UntaggedFunction::kConstructor) {
    printer->AddString("new ");
  } else if (params.include_class_name) {
    const Class& cls = Class::Handle(fun.Owner());
    if (!cls.IsTopLevel()) {
      const Class& mixin = Class::Handle(cls.Mixin());
      printer->AddString(params.name_visibility == Object::kUserVisibleName
                             ? mixin.UserVisibleNameCString()
                             : cls.NameCString(params.name_visibility));
      printer->AddString(".");
    }
  }

  printer->AddString(fun.NameCString(params.name_visibility));

  // Dispatchers that are created with an arguments descriptor need both the
  // name and the saved arguments descriptor to disambiguate.
  if (params.disambiguate_names && fun.HasSavedArgumentsDescriptor()) {
    const auto& args_desc_array = Array::Handle(fun.saved_args_desc());
    const ArgumentsDescriptor args_desc(args_desc_array);
    args_desc.PrintTo(printer);
  }
}

void Function::PrintName(const NameFormattingParams& params,
                         BaseTextBuffer* printer) const {
  if (!IsLocalFunction()) {
    FunctionPrintNameHelper(*this, params, printer);
    return;
  }
  auto& fun = Function::Handle(ptr());
  FunctionPrintNameHelper(fun, params, printer);
}

StringPtr Function::GetSource() const {
  if (IsImplicitConstructor() || is_synthetic()) {
    // We may need to handle more cases when the restrictions on mixins are
    // relaxed. In particular we might start associating some source with the
    // forwarding constructors when it becomes possible to specify a particular
    // constructor from the mixin to use.
    return String::null();
  }
  Zone* zone = Thread::Current()->zone();
  const Script& func_script = Script::Handle(zone, script());

  intptr_t from_line, from_col;
  if (!func_script.GetTokenLocation(token_pos(), &from_line, &from_col)) {
    return String::null();
  }
  intptr_t to_line, to_col;
  if (!func_script.GetTokenLocation(end_token_pos(), &to_line, &to_col)) {
    return String::null();
  }
  intptr_t to_length = func_script.GetTokenLength(end_token_pos());
  if (to_length < 0) {
    return String::null();
  }

  if (to_length == 1) {
    // Handle special cases for end tokens of closures (where we exclude the
    // last token):
    // (1) "foo(() => null, bar);": End token is `,', but we don't print it.
    // (2) "foo(() => null);": End token is ')`, but we don't print it.
    // (3) "var foo = () => null;": End token is `;', but in this case the
    // token semicolon belongs to the assignment so we skip it.
    const String& src = String::Handle(func_script.Source());
    if (src.IsNull() || src.Length() == 0) {
      return Symbols::OptimizedOut().ptr();
    }
    uint16_t end_char = src.CharAt(end_token_pos().Pos());
    if ((end_char == ',') ||  // Case 1.
        (end_char == ')') ||  // Case 2.
        (end_char == ';' && String::Handle(zone, name())
                                .Equals("<anonymous closure>"))) {  // Case 3.
      to_length = 0;
    }
  }

  return func_script.GetSnippet(from_line, from_col, to_line,
                                to_col + to_length);
}

// Construct fingerprint from token stream. The token stream contains also
// arguments.
int32_t Function::SourceFingerprint() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (is_declared_in_bytecode()) {
    return 0;
  }
  return kernel::KernelSourceFingerprintHelper::CalculateFunctionFingerprint(
      *this);
#else
  return 0;
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
}

void Function::SaveICDataMap(
    const ZoneGrowableArray<const ICData*>& deopt_id_to_ic_data,
    const Array& edge_counters_array,
    const Array& coverage_array) const {
#if !defined(DART_PRECOMPILED_RUNTIME)
  // Already installed nothing to do.
  if (ic_data_array() != Array::null()) {
    ASSERT(coverage_array.ptr() == GetCoverageArray());
    return;
  }

  // Compute number of ICData objects to save.
  intptr_t count = 0;
  for (intptr_t i = 0; i < deopt_id_to_ic_data.length(); i++) {
    if (deopt_id_to_ic_data[i] != nullptr) {
      count++;
    }
  }

  // Compress sparse deopt_id_to_ic_data mapping into a linear sequence of
  // ICData objects.
  const Array& array = Array::Handle(
      Array::New(ICDataArrayIndices::kFirstICData + count, Heap::kOld));
  for (intptr_t i = 0, pos = ICDataArrayIndices::kFirstICData;
       i < deopt_id_to_ic_data.length(); i++) {
    if (deopt_id_to_ic_data[i] != nullptr) {
      ASSERT(i == deopt_id_to_ic_data[i]->deopt_id());
      array.SetAt(pos++, *deopt_id_to_ic_data[i]);
    }
  }
  array.SetAt(ICDataArrayIndices::kEdgeCounters, edge_counters_array);
  // Preserve coverage_array which is stored early after graph construction.
  array.SetAt(ICDataArrayIndices::kCoverageData, coverage_array);
  set_ic_data_array(array);
#else   // DART_PRECOMPILED_RUNTIME
  UNREACHABLE();
#endif  // DART_PRECOMPILED_RUNTIME
}

void Function::RestoreICDataMap(
    ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data,
    bool clone_ic_data) const {
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (FLAG_force_clone_compiler_objects) {
    clone_ic_data = true;
  }
  ASSERT(deopt_id_to_ic_data->is_empty());
  Zone* zone = Thread::Current()->zone();
  const Array& saved_ic_data = Array::Handle(zone, ic_data_array());
  if (saved_ic_data.IsNull()) {
    // Could happen with not-yet compiled unoptimized code or force-optimized
    // functions.
    return;
  }
  const intptr_t saved_length = saved_ic_data.Length();
  ASSERT(saved_length > 0);
  if (saved_length > ICDataArrayIndices::kFirstICData) {
    const intptr_t restored_length =
        ICData::Cast(Object::Handle(zone, saved_ic_data.At(saved_length - 1)))
            .deopt_id() +
        1;
    deopt_id_to_ic_data->SetLength(restored_length);
    for (intptr_t i = 0; i < restored_length; i++) {
      (*deopt_id_to_ic_data)[i] = nullptr;
    }
    for (intptr_t i = ICDataArrayIndices::kFirstICData; i < saved_length; i++) {
      ICData& ic_data = ICData::ZoneHandle(zone);
      ic_data ^= saved_ic_data.At(i);
      if (clone_ic_data) {
        const ICData& original_ic_data = ICData::Handle(zone, ic_data.ptr());
        ic_data = ICData::Clone(ic_data);
        ic_data.SetOriginal(original_ic_data);
      }
      ASSERT(deopt_id_to_ic_data->At(ic_data.deopt_id()) == nullptr);
      (*deopt_id_to_ic_data)[ic_data.deopt_id()] = &ic_data;
    }
  }
#else   // DART_PRECOMPILED_RUNTIME
  UNREACHABLE();
#endif  // DART_PRECOMPILED_RUNTIME
}

ArrayPtr Function::GetCoverageArray() const {
  const Array& arr = Array::Handle(ic_data_array());
  if (arr.IsNull()) {
    return Array::null();
  }
  return Array::RawCast(arr.At(ICDataArrayIndices::kCoverageData));
}

void Function::set_ic_data_array(const Array& value) const {
#if defined(DART_DYNAMIC_MODULES)
  ASSERT(!HasBytecode());
#endif
  untag()->set_ic_data_array_or_bytecode<std::memory_order_release>(
      value.ptr());
}

ArrayPtr Function::ic_data_array() const {
  ObjectPtr value =
      untag()->ic_data_array_or_bytecode<std::memory_order_acquire>();
#if defined(DART_DYNAMIC_MODULES)
  if (value->IsBytecode()) {
    return Array::null();
  }
#endif
  return Array::RawCast(value);
}

void Function::ClearICDataArray() const {
  set_ic_data_array(Array::null_array());
}

ICDataPtr Function::FindICData(intptr_t deopt_id) const {
  const Array& array = Array::Handle(ic_data_array());
  ICData& ic_data = ICData::Handle();
  for (intptr_t i = ICDataArrayIndices::kFirstICData; i < array.Length(); i++) {
    ic_data ^= array.At(i);
    if (ic_data.deopt_id() == deopt_id) {
      return ic_data.ptr();
    }
  }
  return ICData::null();
}

void Function::SetDeoptReasonForAll(intptr_t deopt_id,
                                    ICData::DeoptReasonId reason) {
  const Array& array = Array::Handle(ic_data_array());
  ICData& ic_data = ICData::Handle();
  for (intptr_t i = ICDataArrayIndices::kFirstICData; i < array.Length(); i++) {
    ic_data ^= array.At(i);
    if (ic_data.deopt_id() == deopt_id) {
      ic_data.AddDeoptReason(reason);
    }
  }
}

bool Function::CheckSourceFingerprint(int32_t fp, const char* kind) const {
#if defined(DEBUG)
#if !defined(DART_PRECOMPILED_RUNTIME)
  // Check that the function is marked as recognized via the vm:recognized
  // pragma. This is so that optimizations that change the signature will know
  // not to touch it.
  if (kind != nullptr && !MethodRecognizer::IsMarkedAsRecognized(*this, kind)) {
    OS::PrintErr(
        "Recognized method %s should be marked with: "
        "@pragma(\"vm:recognized\", \"%s\")\n",
        ToQualifiedCString(), kind);
    return false;
  }
#endif

  if (IsolateGroup::Current()->obfuscate() || FLAG_precompiled_mode ||
      (Dart::vm_snapshot_kind() != Snapshot::kNone)) {
    return true;  // The kernel structure has been altered, skip checking.
  }

  ASSERT(!is_declared_in_bytecode());

  if (SourceFingerprint() != fp) {
    // This output can be copied into a file, then used with sed
    // to replace the old values.
    // sed -i.bak -f /tmp/newkeys \
    //    runtime/vm/compiler/recognized_methods_list.h
    THR_Print("s/0x%08x/0x%08x/\n", fp, SourceFingerprint());
    return false;
  }
#endif  // defined(DEBUG)
  return true;
}

CodePtr Function::EnsureHasCode() const {
  if (HasCode()) {
    return CurrentCode();
  }
  Thread* thread = Thread::Current();
  ASSERT(thread->IsDartMutatorThread());
  DEBUG_ASSERT(thread->TopErrorHandlerIsExitFrame());
  Zone* zone = thread->zone();
  const Object& result = Object::Handle(zone, EnsureHasCodeNoThrow());
  if (result.IsError()) {
    if (result.ptr() == Object::out_of_memory_error().ptr()) {
      Exceptions::ThrowOOM();
      UNREACHABLE();
    }
    if (result.IsLanguageError()) {
      Exceptions::ThrowCompileTimeError(LanguageError::Cast(result));
      UNREACHABLE();
    }
    Exceptions::PropagateError(Error::Cast(result));
    UNREACHABLE();
  } else {
    return Code::Cast(result).ptr();
  }
}

ObjectPtr Function::EnsureHasCodeNoThrow() const {
  if (HasCode()) {
    return CurrentCode();
  }
  Thread* thread = Thread::Current();
  ASSERT(thread->IsDartMutatorThread());
  Zone* zone = thread->zone();
  const Object& result =
      Object::Handle(zone, Compiler::CompileFunction(thread, *this));
  if (result.IsError()) {
    return result.ptr();
  }
  // Compiling in unoptimized mode should never fail if there are no errors.
  RELEASE_ASSERT(HasCode());
  ASSERT(ForceOptimize() || unoptimized_code() == result.ptr());
  return CurrentCode();
}

bool Function::NeedsMonomorphicCheckedEntry(Zone* zone) const {
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (!IsDynamicFunction()) {
    return false;
  }

  // For functions which need an args descriptor the switchable call sites will
  // transition directly to calling via a stub (and therefore never call the
  // monomorphic entry).
  //
  // See runtime_entry.cc:DEFINE_RUNTIME_ENTRY(UnlinkedCall)
  if (PrologueNeedsArgumentsDescriptor()) {
    return false;
  }

  // All dyn:* forwarders are called via SwitchableCalls and all except the ones
  // with `PrologueNeedsArgumentsDescriptor()` transition into monomorphic
  // state.
  if (Function::IsDynamicInvocationForwarderName(name())) {
    return true;
  }

  // AOT mode uses table dispatch.
  // In JIT mode all instance calls use switchable calls.
  if (!FLAG_precompiled_mode) {
    return true;
  }

  // Any method from the class with a dynamically loaded subtype
  // can be called via switchable call (when cid range check fails
  // during conditional table dispatch).
  if (Class::Handle(zone, Owner()).has_dynamically_extendable_subtypes()) {
    return true;
  }

  // Only if there are dynamic callers and if we didn't create a dyn:* forwarder
  // for it do we need the monomorphic checked entry.
  return HasDynamicCallers(zone) && !NeedsDynamicInvocationForwarder();
#else
  UNREACHABLE();
  return true;
#endif
}

bool Function::HasDynamicCallers(Zone* zone) const {
#if !defined(DART_PRECOMPILED_RUNTIME)
  // Use the results of TFA to determine whether this function is ever
  // called dynamically, i.e. using switchable calls.
  kernel::ProcedureAttributesMetadata metadata;
  metadata = kernel::ProcedureAttributesOf(*this, zone);
  if (IsGetterFunction() || IsImplicitGetterFunction() || IsMethodExtractor()) {
    // Dynamic method call through field/getter involves dynamic call of
    // the field/getter.
    return metadata.getter_called_dynamically ||
           metadata.method_or_setter_called_dynamically;
  } else {
    return metadata.method_or_setter_called_dynamically;
  }
#else
  UNREACHABLE();
  return true;
#endif
}

bool Function::PrologueNeedsArgumentsDescriptor() const {
  // These functions have a saved compile-time arguments descriptor that is
  // used in lieu of the runtime arguments descriptor in generated IL.
  if (HasSavedArgumentsDescriptor()) {
    return false;
  }
#if defined(DART_DYNAMIC_MODULES)
  // Entering interpreter needs arguments descriptor.
  if (is_declared_in_bytecode()) {
    return true;
  }
#endif
  // The prologue of those functions need to examine the arg descriptor for
  // various purposes.
  return IsGeneric() || HasOptionalParameters();
}

bool Function::MayHaveUncheckedEntryPoint() const {
  return FLAG_enable_multiple_entrypoints &&
         (NeedsTypeArgumentTypeChecks() || NeedsArgumentTypeChecks());
}

intptr_t Function::SourceSize() const {
  const TokenPosition& start = token_pos();
  const TokenPosition& end = end_token_pos();
  if (!end.IsReal() || start.IsNoSource() || start.IsClassifying()) {
    // No source information, so just return 0.
    return 0;
  }
  if (start.IsSynthetic()) {
    // Try and approximate the source size using the parent's source size.
    const auto& parent = Function::Handle(parent_function());
    ASSERT(!parent.IsNull());
    const intptr_t parent_size = parent.SourceSize();
    if (parent_size == 0) {
      return parent_size;
    }
    // Parent must have a real ending position.
    return parent_size - (parent.end_token_pos().Pos() - end.Pos());
  }
  return end.Pos() - start.Pos();
}

const char* Function::ToCString() const {
  if (IsNull()) {
    return "Function: null";
  }
  Zone* zone = Thread::Current()->zone();
  ZoneTextBuffer buffer(zone);
  buffer.Printf("Function '%s':", String::Handle(zone, name()).ToCString());
  if (is_static()) {
    buffer.AddString(" static");
  }
  if (is_abstract()) {
    buffer.AddString(" abstract");
  }
  switch (kind()) {
    case UntaggedFunction::kRegularFunction:
    case UntaggedFunction::kClosureFunction:
    case UntaggedFunction::kImplicitClosureFunction:
    case UntaggedFunction::kGetterFunction:
    case UntaggedFunction::kSetterFunction:
      break;
    case UntaggedFunction::kConstructor:
      buffer.AddString(is_static() ? " factory" : " constructor");
      break;
    case UntaggedFunction::kImplicitGetter:
      buffer.AddString(" getter");
      break;
    case UntaggedFunction::kImplicitSetter:
      buffer.AddString(" setter");
      break;
    case UntaggedFunction::kImplicitStaticGetter:
      buffer.AddString(" static-getter");
      break;
    case UntaggedFunction::kFieldInitializer:
      buffer.AddString(" field-initializer");
      break;
    case UntaggedFunction::kMethodExtractor:
      buffer.AddString(" method-extractor");
      break;
    case UntaggedFunction::kNoSuchMethodDispatcher:
      buffer.AddString(" no-such-method-dispatcher");
      break;
    case UntaggedFunction::kDynamicInvocationForwarder:
      buffer.AddString(" dynamic-invocation-forwarder");
      break;
    case UntaggedFunction::kInvokeFieldDispatcher:
      buffer.AddString(" invoke-field-dispatcher");
      break;
    case UntaggedFunction::kIrregexpFunction:
      buffer.AddString(" irregexp-function");
      break;
    case UntaggedFunction::kFfiTrampoline:
      buffer.AddString(" ffi-trampoline-function");
      break;
    case UntaggedFunction::kRecordFieldGetter:
      buffer.AddString(" record-field-getter");
      break;
    default:
      UNREACHABLE();
  }
  if (HasSavedArgumentsDescriptor()) {
    const auto& args_desc_array = Array::Handle(zone, saved_args_desc());
    const ArgumentsDescriptor args_desc(args_desc_array);
    buffer.AddChar('[');
    args_desc.PrintTo(&buffer);
    buffer.AddChar(']');
  }
  if (is_const()) {
    buffer.AddString(" const");
  }
  buffer.AddChar('.');
  return buffer.buffer();
}

void FunctionType::set_packed_parameter_counts(
    uint32_t packed_parameter_counts) const {
  untag()->packed_parameter_counts_ = packed_parameter_counts;
}

void FunctionType::set_packed_type_parameter_counts(
    uint16_t packed_type_parameter_counts) const {
  untag()->packed_type_parameter_counts_ = packed_type_parameter_counts;
}

void FunctionType::set_num_implicit_parameters(intptr_t value) const {
  ASSERT(value >= 0);
  untag()->packed_parameter_counts_.Update<PackedNumImplicitParameters>(value);
}

void ClosureData::set_default_type_arguments_instantiation_mode(
    InstantiationMode value) const {
  untag()->packed_fields_.Update<PackedInstantiationMode>(value);
}

Function::AwaiterLink ClosureData::awaiter_link() const {
  const uint8_t depth =
      untag()
          ->packed_fields_.Read<UntaggedClosureData::PackedAwaiterLinkDepth>();
  const uint8_t index =
      untag()
          ->packed_fields_.Read<UntaggedClosureData::PackedAwaiterLinkIndex>();
  return {depth, index};
}

void ClosureData::set_awaiter_link(Function::AwaiterLink link) const {
  untag()->packed_fields_.Update<UntaggedClosureData::PackedAwaiterLinkDepth>(
      link.depth);
  untag()->packed_fields_.Update<UntaggedClosureData::PackedAwaiterLinkIndex>(
      link.index);
}

ClosureDataPtr ClosureData::New() {
  ASSERT(Object::closure_data_class() != Class::null());
  return Object::Allocate<ClosureData>(Heap::kOld);
}

const char* ClosureData::ToCString() const {
  if (IsNull()) {
    return "ClosureData: null";
  }
  auto const zone = Thread::Current()->zone();
  ZoneTextBuffer buffer(zone);
  buffer.Printf("ClosureData: context_scope: 0x%" Px "",
                static_cast<uword>(context_scope()));
  buffer.AddString(" parent_function: ");
  if (parent_function() == Object::null()) {
    buffer.AddString("null");
  } else {
    buffer.AddString(Object::Handle(parent_function()).ToCString());
  }
  buffer.Printf(" implicit_static_closure: 0x%" Px "",
                static_cast<uword>(implicit_static_closure()));
  return buffer.buffer();
}

void FunctionType::set_num_fixed_parameters(intptr_t value) const {
  ASSERT(value >= 0);
  untag()->packed_parameter_counts_.Update<PackedNumFixedParameters>(value);
}

void FfiTrampolineData::set_callback_target(const Function& value) const {
  untag()->set_callback_target(value.ptr());
}

void FunctionType::SetNumOptionalParameters(
    intptr_t value,
    bool are_optional_positional) const {
  // HasOptionalNamedParameters only checks this bit, so only set it if there
  // are actual named parameters.
  untag()->packed_parameter_counts_.Update<PackedHasNamedOptionalParameters>(
      (value > 0) && !are_optional_positional);
  untag()->packed_parameter_counts_.Update<PackedNumOptionalParameters>(value);
}

FunctionTypePtr FunctionType::New(Heap::Space space) {
  return Object::Allocate<FunctionType>(space);
}

FunctionTypePtr FunctionType::New(intptr_t num_parent_type_arguments,
                                  Nullability nullability,
                                  Heap::Space space) {
  Zone* Z = Thread::Current()->zone();
  const FunctionType& result =
      FunctionType::Handle(Z, FunctionType::New(space));
  result.set_packed_parameter_counts(0);
  result.set_packed_type_parameter_counts(0);
  result.set_named_parameter_names(Object::empty_array());
  result.SetNumParentTypeArguments(num_parent_type_arguments);
  result.SetHash(0);
  result.set_flags(0);
  result.set_nullability(nullability);
  result.set_type_state(UntaggedAbstractType::kAllocated);
  result.InitializeTypeTestingStubNonAtomic(
      Code::Handle(Z, TypeTestingStubGenerator::DefaultCodeForType(result)));
  return result.ptr();
}

FunctionTypePtr FunctionType::Clone(const FunctionType& orig,
                                    Heap::Space space) {
  if (orig.IsGeneric()) {
    // Need a deep clone in order to update owners of type parameters.
    return FunctionType::RawCast(
        orig.UpdateFunctionTypes(0, kAllFree, space, nullptr));
  } else {
    return FunctionType::RawCast(Object::Clone(orig, space));
  }
}

const char* FunctionType::ToUserVisibleCString() const {
  Zone* zone = Thread::Current()->zone();
  ZoneTextBuffer printer(zone);
  Print(kUserVisibleName, &printer);
  return printer.buffer();
}

StringPtr FunctionType::ToUserVisibleString() const {
  Thread* thread = Thread::Current();
  ZoneTextBuffer printer(thread->zone());
  Print(kUserVisibleName, &printer);
  return Symbols::New(thread, printer.buffer());
}

const char* FunctionType::ToCString() const {
  if (IsNull()) {
    return "FunctionType: null";
  }
  Zone* zone = Thread::Current()->zone();
  ZoneTextBuffer printer(zone);
  const char* suffix = NullabilitySuffix(kInternalName);
  if (suffix[0] != '\0') {
    printer.AddString("(");
  }
  Print(kInternalName, &printer);
  if (suffix[0] != '\0') {
    printer.AddString(")");
    printer.AddString(suffix);
  }
  return printer.buffer();
}

void ClosureData::set_context_scope(const ContextScope& value) const {
  untag()->set_context_scope(value.ptr());
}

void ClosureData::set_implicit_static_closure(const Closure& closure) const {
  ASSERT(!closure.IsNull());
  ASSERT(untag()->closure() == Closure::null());
  untag()->set_closure<std::memory_order_release>(closure.ptr());
}

void FfiTrampolineData::set_c_signature(const FunctionType& value) const {
  untag()->set_c_signature(value.ptr());
}

void FfiTrampolineData::set_callback_id(int32_t callback_id) const {
  StoreNonPointer(&untag()->callback_id_, callback_id);
}

void FfiTrampolineData::set_callback_exceptional_return(
    const Instance& value) const {
  untag()->set_callback_exceptional_return(value.ptr());
}

void FfiTrampolineData::set_ffi_function_kind(FfiCallbackKind kind) const {
  StoreNonPointer(&untag()->ffi_function_kind_, static_cast<uint8_t>(kind));
}

FfiTrampolineDataPtr FfiTrampolineData::New() {
  ASSERT(Object::ffi_trampoline_data_class() != Class::null());
  const auto& data = FfiTrampolineData::Handle(
      Object::Allocate<FfiTrampolineData>(Heap::kOld));
  data.set_callback_id(-1);
  return data.ptr();
}

const char* FfiTrampolineData::ToCString() const {
  const FunctionType& c_sig = FunctionType::Handle(c_signature());
  return OS::SCreate(Thread::Current()->zone(),
                     "TrampolineData: c_signature=%s",
                     c_sig.ToUserVisibleCString());
}

FieldPtr Field::CloneFromOriginal() const {
  return this->Clone(*this);
}

FieldPtr Field::Original() const {
  if (IsNull()) {
    return Field::null();
  }
  if (untag()->owner()->IsField()) {
    return static_cast<FieldPtr>(untag()->owner());
  }
  return this->ptr();
}

intptr_t Field::guarded_cid() const {
#if defined(DEBUG)
  // This assertion ensures that the cid seen by the background compiler is
  // consistent. So the assertion passes if the field is a clone. It also
  // passes if the field is static, because we don't use field guards on
  // static fields. It also passes if we're compiling unoptimized
  // code (in which case the caller might get different answers if it obtains
  // the guarded cid multiple times).
  Thread* thread = Thread::Current();
#if defined(DART_PRECOMPILED_RUNTIME)
  ASSERT(!thread->IsInsideCompiler() || is_static());
#else
  ASSERT(!thread->IsInsideCompiler() ||
         ((CompilerState::Current().should_clone_fields() == !IsOriginal())) ||
         is_static());
#endif
#endif
  return LoadNonPointer<ClassIdTagType, std::memory_order_relaxed>(
      &untag()->guarded_cid_);
}

bool Field::is_nullable() const {
#if defined(DEBUG)
  // Same assert as guarded_cid(), because is_nullable() also needs to be
  // consistent for the background compiler.
  Thread* thread = Thread::Current();
#if defined(DART_PRECOMPILED_RUNTIME)
  ASSERT(!thread->IsInsideCompiler() || is_static());
#else
  ASSERT(!thread->IsInsideCompiler() ||
         ((CompilerState::Current().should_clone_fields() == !IsOriginal())) ||
         is_static());
#endif
#endif
  return is_nullable_unsafe();
}

void Field::SetOriginal(const Field& value) const {
  ASSERT(value.IsOriginal());
  ASSERT(!value.IsNull());
  untag()->set_owner(static_cast<ObjectPtr>(value.ptr()));
}

StringPtr Field::GetterName(const String& field_name) {
  return String::Concat(Symbols::GetterPrefix(), field_name);
}

StringPtr Field::GetterSymbol(const String& field_name) {
  return Symbols::FromGet(Thread::Current(), field_name);
}

StringPtr Field::LookupGetterSymbol(const String& field_name) {
  return Symbols::LookupFromGet(Thread::Current(), field_name);
}

StringPtr Field::SetterName(const String& field_name) {
  return String::Concat(Symbols::SetterPrefix(), field_name);
}

StringPtr Field::SetterSymbol(const String& field_name) {
  return Symbols::FromSet(Thread::Current(), field_name);
}

StringPtr Field::LookupSetterSymbol(const String& field_name) {
  return Symbols::LookupFromSet(Thread::Current(), field_name);
}

StringPtr Field::NameFromGetter(const String& getter_name) {
  return Symbols::New(Thread::Current(), getter_name, kGetterPrefixLength,
                      getter_name.Length() - kGetterPrefixLength);
}

StringPtr Field::NameFromSetter(const String& setter_name) {
  return Symbols::New(Thread::Current(), setter_name, kSetterPrefixLength,
                      setter_name.Length() - kSetterPrefixLength);
}

StringPtr Field::NameFromInit(const String& init_name) {
  return Symbols::New(Thread::Current(), init_name, kInitPrefixLength,
                      init_name.Length() - kInitPrefixLength);
}

bool Field::IsGetterName(const String& function_name) {
  return function_name.StartsWith(Symbols::GetterPrefix());
}

bool Field::IsSetterName(const String& function_name) {
  return function_name.StartsWith(Symbols::SetterPrefix());
}

bool Field::IsInitName(const String& function_name) {
  return function_name.StartsWith(Symbols::InitPrefix());
}

void Field::set_name(const String& value) const {
  ASSERT(value.IsSymbol());
  ASSERT(IsOriginal());
  untag()->set_name(value.ptr());
}

ObjectPtr Field::RawOwner() const {
  if (IsOriginal()) {
    return untag()->owner();
  } else {
    const Field& field = Field::Handle(Original());
    ASSERT(field.IsOriginal());
    ASSERT(!Object::Handle(field.untag()->owner()).IsField());
    return field.untag()->owner();
  }
}

ClassPtr Field::Owner() const {
  const Field& field = Field::Handle(Original());
  ASSERT(field.IsOriginal());
  const Object& obj = Object::Handle(field.untag()->owner());
  if (obj.IsClass()) {
    return Class::Cast(obj).ptr();
  }
  ASSERT(obj.IsPatchClass());
  return PatchClass::Cast(obj).wrapped_class();
}

ScriptPtr Field::Script() const {
  // NOTE(turnidge): If you update this function, you probably want to
  // update Class::PatchFieldsAndFunctions() at the same time.
  const Field& field = Field::Handle(Original());
  ASSERT(field.IsOriginal());
  const Object& obj = Object::Handle(field.untag()->owner());
  if (obj.IsClass()) {
    return Class::Cast(obj).script();
  }
  ASSERT(obj.IsPatchClass());
  return PatchClass::Cast(obj).script();
}

#if !defined(DART_PRECOMPILED_RUNTIME)
KernelProgramInfoPtr Field::KernelProgramInfo() const {
  const auto& owner = Object::Handle(RawOwner());
  if (owner.IsClass()) {
    return Class::Cast(owner).KernelProgramInfo();
  }
  return PatchClass::Cast(owner).kernel_program_info();
}
#endif

uint32_t Field::Hash() const {
  return String::HashRawSymbol(name());
}

#if defined(DART_DYNAMIC_MODULES)
bool Field::is_declared_in_bytecode() const {
  return Class::Handle(Owner()).is_declared_in_bytecode();
}
#endif

void Field::InheritKernelOffsetFrom(const Field& src) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  StoreNonPointer(&untag()->kernel_offset_, src.untag()->kernel_offset_);
#endif
}

#if !defined(DART_PRECOMPILED_RUNTIME)
TypedDataViewPtr Field::KernelLibrary() const {
  const intptr_t kernel_library_index = KernelLibraryIndex();
  if (kernel_library_index == -1) return TypedDataView::null();
  const auto& info = KernelProgramInfo::Handle(KernelProgramInfo());
  return info.KernelLibrary(kernel_library_index);
}

intptr_t Field::KernelLibraryOffset() const {
  const intptr_t kernel_library_index = KernelLibraryIndex();
  if (kernel_library_index == -1) return 0;
  const auto& info = KernelProgramInfo::Handle(KernelProgramInfo());
  return info.KernelLibraryStartOffset(kernel_library_index);
}

intptr_t Field::KernelLibraryIndex() const {
  const Object& obj = Object::Handle(untag()->owner());
  // During background JIT compilation field objects are copied
  // and copy points to the original field via the owner field.
  if (obj.IsField()) {
    return Field::Cast(obj).KernelLibraryIndex();
  } else if (obj.IsClass()) {
    const auto& lib = Library::Handle(Class::Cast(obj).library());
    return lib.kernel_library_index();
  }
  ASSERT(obj.IsPatchClass());
  return PatchClass::Cast(obj).kernel_library_index();
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

void Field::SetFieldTypeSafe(const AbstractType& value) const {
  ASSERT(IsOriginal());
  ASSERT(!value.IsNull());
  if (value.ptr() != type()) {
    untag()->set_type(value.ptr());
  }
}

// Called at finalization time
void Field::SetFieldType(const AbstractType& value) const {
  DEBUG_ASSERT(
      IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  SetFieldTypeSafe(value);
}

#if !defined(DART_PRECOMPILED_RUNTIME)
void Field::set_exact_type(const AbstractType& value) const {
  DEBUG_ASSERT(
      IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  ASSERT(IsOriginal());
  untag()->set_exact_type(value.ptr());
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

FieldPtr Field::New() {
  ASSERT(Object::field_class() != Class::null());
  return Object::Allocate<Field>(Heap::kOld);
}

void Field::InitializeNew(const Field& result,
                          const String& name,
                          bool is_static,
                          bool is_final,
                          bool is_const,
                          bool is_reflectable,
                          bool is_late,
                          const Object& owner,
                          TokenPosition token_pos,
                          TokenPosition end_token_pos) {
  result.set_name(name);
  result.set_is_static(is_static);
  if (is_static) {
    result.set_field_id_unsafe(-1);
  } else {
    result.SetOffset(0, 0);
  }
  result.set_is_final(is_final);
  result.set_is_const(is_const);
  result.set_is_reflectable(is_reflectable);
  result.set_is_late(is_late);
  result.set_owner(owner);
  result.set_token_pos(token_pos);
  result.set_end_token_pos(end_token_pos);
  result.set_has_nontrivial_initializer_unsafe(false);
  result.set_has_initializer_unsafe(false);
  // We will make unboxing decision once we read static type or
  // in KernelLoader::ReadInferredType.
  result.set_is_unboxed_unsafe(false);
  result.set_initializer_changed_after_initialization(false);
  NOT_IN_PRECOMPILED(result.set_kernel_offset(0));
  result.set_has_pragma(false);
  result.set_static_type_exactness_state_unsafe(
      StaticTypeExactnessState::NotTracking());
  auto isolate_group = IsolateGroup::Current();

// Use field guards if they are enabled and the isolate has never reloaded.
// TODO(johnmccutchan): The reload case assumes the worst case (everything is
// dynamic and possibly null). Attempt to relax this later.
//
// Do not use field guards for late fields as late field initialization
// doesn't update guarded cid and length.
#if defined(PRODUCT)
  const bool use_guarded_cid =
      FLAG_precompiled_mode || (isolate_group->use_field_guards() && !is_late);
#else
  const bool use_guarded_cid =
      FLAG_precompiled_mode ||
      (isolate_group->use_field_guards() &&
       !isolate_group->HasAttemptedReload() && !is_late);
#endif  // !defined(PRODUCT)
  result.set_guarded_cid_unsafe(use_guarded_cid ? kIllegalCid : kDynamicCid);
  result.set_is_nullable_unsafe(use_guarded_cid ? false : true);
  result.set_guarded_list_length_in_object_offset_unsafe(
      Field::kUnknownLengthOffset);
  // Presently, we only attempt to remember the list length for final fields.
  if (is_final && use_guarded_cid) {
    result.set_guarded_list_length_unsafe(Field::kUnknownFixedLength);
  } else {
    result.set_guarded_list_length_unsafe(Field::kNoFixedLength);
  }
}

FieldPtr Field::New(const String& name,
                    bool is_static,
                    bool is_final,
                    bool is_const,
                    bool is_reflectable,
                    bool is_late,
                    const Object& owner,
                    const AbstractType& type,
                    TokenPosition token_pos,
                    TokenPosition end_token_pos) {
  ASSERT(!owner.IsNull());
  const Field& result = Field::Handle(Field::New());
  InitializeNew(result, name, is_static, is_final, is_const, is_reflectable,
                is_late, owner, token_pos, end_token_pos);
  result.SetFieldTypeSafe(type);
#if !defined(DART_PRECOMPILED_RUNTIME)
  compiler::target::UnboxFieldIfSupported(result, type);
#endif
  return result.ptr();
}

FieldPtr Field::NewTopLevel(const String& name,
                            bool is_final,
                            bool is_const,
                            bool is_late,
                            const Object& owner,
                            TokenPosition token_pos,
                            TokenPosition end_token_pos) {
  ASSERT(!owner.IsNull());
  const Field& result = Field::Handle(Field::New());
  InitializeNew(result, name, true,       /* is_static */
                is_final, is_const, true, /* is_reflectable */
                is_late, owner, token_pos, end_token_pos);
  return result.ptr();
}

FieldPtr Field::Clone(const Field& original) const {
  if (original.IsNull()) {
    return Field::null();
  }
  ASSERT(original.IsOriginal());
  Field& clone = Field::Handle();
  // Using relaxed loading is fine because concurrent fields changes are all
  // guarded, will be reconciled during optimized code installation.
  clone ^= Object::Clone(*this, Heap::kOld, /*load_with_relaxed_atomics=*/true);
  clone.SetOriginal(original);
  clone.InheritKernelOffsetFrom(original);
  return clone.ptr();
}

int32_t Field::SourceFingerprint() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (is_declared_in_bytecode()) {
    return 0;
  }
  return kernel::KernelSourceFingerprintHelper::CalculateFieldFingerprint(
      *this);
#else
  return 0;
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
}

StringPtr Field::InitializingExpression() const {
  UNREACHABLE();
  return String::null();
}

const char* Field::UserVisibleNameCString() const {
  NoSafepointScope no_safepoint;
  if (FLAG_show_internal_names) {
    return String::Handle(name()).ToCString();
  }
  return String::ScrubName(String::Handle(name()),
                           is_extension_member() || is_extension_type_member());
}

StringPtr Field::UserVisibleName() const {
  if (FLAG_show_internal_names) {
    return name();
  }
  return Symbols::New(
      Thread::Current(),
      String::ScrubName(String::Handle(name()),
                        is_extension_member() || is_extension_type_member()));
}

intptr_t Field::guarded_list_length() const {
  return Smi::Value(untag()->guarded_list_length());
}

void Field::set_guarded_list_length_unsafe(intptr_t list_length) const {
  ASSERT(IsOriginal());
  untag()->set_guarded_list_length(Smi::New(list_length));
}

intptr_t Field::guarded_list_length_in_object_offset() const {
  return untag()->guarded_list_length_in_object_offset_ + kHeapObjectTag;
}

void Field::set_guarded_list_length_in_object_offset_unsafe(
    intptr_t list_length_offset) const {
  ASSERT(IsOriginal());
  StoreNonPointer<int8_t, int8_t, std::memory_order_relaxed>(
      &untag()->guarded_list_length_in_object_offset_,
      static_cast<int8_t>(list_length_offset - kHeapObjectTag));
  ASSERT(guarded_list_length_in_object_offset() == list_length_offset);
}

bool Field::NeedsSetter() const {
  // According to the Dart language specification, final fields don't have
  // a setter, except late final fields without initializer.
  if (is_final()) {
    // Late final fields without initializer always need a setter to check
    // if they are already initialized.
    if (is_late() && !has_initializer()) {
      return true;
    }
    return false;
  }

  // Instance non-final fields always need a setter.
  if (!is_static()) {
    return true;
  }

  // Otherwise, setters for static fields can be omitted
  // and fields can be accessed directly.
  return false;
}

bool Field::NeedsGetter() const {
  // All instance fields need a getter.
  if (!is_static()) return true;

  // Static fields also need a getter if they have a non-trivial initializer,
  // because it needs to be initialized lazily.
  if (has_nontrivial_initializer()) return true;

  // Static late fields with no initializer also need a getter, to check if it's
  // been initialized.
  return is_late() && !has_initializer();
}

const char* Field::ToCString() const {
  NoSafepointScope no_safepoint;
  if (IsNull()) {
    return "Field: null";
  }
  const char* kF0 = is_static() ? " static" : "";
  const char* kF1 = is_late() ? " late" : "";
  const char* kF2 = is_final() ? " final" : "";
  const char* kF3 = is_const() ? " const" : "";
  const char* kF4 = is_shared() ? " shared" : "";
  const char* field_name = String::Handle(name()).ToCString();
  const Class& cls = Class::Handle(Owner());
  const char* cls_name = String::Handle(cls.Name()).ToCString();
  return OS::SCreate(Thread::Current()->zone(), "Field <%s.%s>:%s%s%s%s%s",
                     cls_name, field_name, kF0, kF1, kF2, kF3, kF4);
}

// Build a closure object that gets (or sets) the contents of a static
// field f and cache the closure in a newly created static field
// named #f (or #f= in case of a setter).
InstancePtr Field::AccessorClosure(bool make_setter) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  ASSERT(is_static());
  const Class& field_owner = Class::Handle(zone, Owner());

  String& closure_name = String::Handle(zone, this->name());
  closure_name = Symbols::FromConcat(thread, Symbols::HashMark(), closure_name);
  if (make_setter) {
    closure_name =
        Symbols::FromConcat(thread, Symbols::HashMark(), closure_name);
  }

  Field& closure_field = Field::Handle(zone);
  closure_field = field_owner.LookupStaticField(closure_name);
  if (!closure_field.IsNull()) {
    ASSERT(closure_field.is_static());
    const Instance& closure =
        Instance::Handle(zone, Instance::RawCast(closure_field.StaticValue()));
    ASSERT(!closure.IsNull());
    ASSERT(closure.IsClosure());
    return closure.ptr();
  }

  UNREACHABLE();
  return Instance::null();
}

InstancePtr Field::GetterClosure() const {
  return AccessorClosure(false);
}

InstancePtr Field::SetterClosure() const {
  return AccessorClosure(true);
}

WeakArrayPtr Field::dependent_code() const {
  DEBUG_ASSERT(
      IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
  return untag()->dependent_code();
}

void Field::set_dependent_code(const WeakArray& array) const {
  ASSERT(IsOriginal());
  DEBUG_ASSERT(
      IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  untag()->set_dependent_code(array.ptr());
}

class FieldDependentArray : public WeakCodeReferences {
 public:
  explicit FieldDependentArray(const Field& field)
      : WeakCodeReferences(WeakArray::Handle(field.dependent_code())),
        field_(field) {}

  virtual void UpdateArrayTo(const WeakArray& value) {
    field_.set_dependent_code(value);
  }

  virtual void ReportDeoptimization(const Code& code) {
    if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
      Function& function = Function::Handle(code.function());
      THR_Print("Deoptimizing %s because guard on field %s failed.\n",
                function.ToFullyQualifiedCString(), field_.ToCString());
    }
  }

  virtual void ReportSwitchingCode(const Code& code) {
    if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
      Function& function = Function::Handle(code.function());
      THR_Print(
          "Switching '%s' to unoptimized code because guard"
          " on field '%s' was violated.\n",
          function.ToFullyQualifiedCString(), field_.ToCString());
    }
  }

 private:
  const Field& field_;
  DISALLOW_COPY_AND_ASSIGN(FieldDependentArray);
};

void Field::RegisterDependentCode(const Code& code) const {
  ASSERT(IsOriginal());
  DEBUG_ASSERT(IsMutatorOrAtDeoptSafepoint());
  ASSERT(code.is_optimized());
  FieldDependentArray a(*this);
  a.Register(code);
}

void Field::DeoptimizeDependentCode(bool are_mutators_stopped) const {
  DEBUG_ASSERT(
      IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  ASSERT(IsOriginal());
  FieldDependentArray a(*this);
  if (FLAG_trace_deoptimization && a.HasCodes()) {
    THR_Print("Deopt for field guard (field %s)\n", ToCString());
  }
  a.DisableCode(are_mutators_stopped);
}

bool Field::IsConsistentWith(const Field& other) const {
  return (untag()->guarded_cid_ == other.untag()->guarded_cid_) &&
         (untag()->is_nullable_ == other.untag()->is_nullable_) &&
         (untag()->guarded_list_length() ==
          other.untag()->guarded_list_length()) &&
         (is_unboxed() == other.is_unboxed()) &&
         (static_type_exactness_state().Encode() ==
          other.static_type_exactness_state().Encode());
}

bool Field::IsUninitialized() const {
  Thread* thread = Thread::Current();
  const FieldTable* field_table = thread->isolate()->field_table();
  const ObjectPtr raw_value = field_table->At(field_id());
  return raw_value == Object::sentinel().ptr();
}

FunctionPtr Field::EnsureInitializerFunction() const {
  ASSERT(has_nontrivial_initializer());
  ASSERT(IsOriginal());
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Function& initializer = Function::Handle(zone, InitializerFunction());
  if (initializer.IsNull()) {
#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES)
    UNREACHABLE();
#else
    SafepointMutexLocker ml(
        thread->isolate_group()->initializer_functions_mutex());
    // Double check after grabbing the lock.
    initializer = InitializerFunction();
    if (initializer.IsNull()) {
      initializer = CreateFieldInitializerFunction(thread);
    }
#endif
  }
  return initializer.ptr();
}

#if !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES)

FunctionPtr Field::CreateFieldInitializerFunction(Thread* thread) const {
  Zone* zone = thread->zone();
  ASSERT(InitializerFunction() == Function::null());

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

  const auto& field_owner = Class::Handle(zone, Owner());

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

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

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

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

void Field::SetInitializerFunction(const Function& initializer) const {
  ASSERT(IsOriginal());
  ASSERT(IsolateGroup::Current()
             ->initializer_functions_mutex()
             ->IsOwnedByCurrentThread());
  // We have to ensure that all stores into the initializer function object
  // happen before releasing the pointer to the initializer as it may be
  // accessed without grabbing the lock.
  untag()->set_initializer_function<std::memory_order_release>(
      initializer.ptr());
}

#endif  // !defined(DART_PRECOMPILED_RUNTIME) || defined(DART_DYNAMIC_MODULES)

bool Field::HasInitializerFunction() const {
  return untag()->initializer_function() != Function::null();
}

ErrorPtr Field::InitializeInstance(const Instance& instance) const {
  ASSERT(IsOriginal());
  ASSERT(is_instance());
  ASSERT(instance.GetField(*this) == Object::sentinel().ptr());
  Object& value = Object::Handle();

  if (has_nontrivial_initializer()) {
    const Function& initializer = Function::Handle(EnsureInitializerFunction());
    const Array& args = Array::Handle(Array::New(1));
    args.SetAt(0, instance);
    value = DartEntry::InvokeFunction(initializer, args);
    if (!value.IsNull() && value.IsError()) {
      return Error::Cast(value).ptr();
    }
  } else {
    if (is_late() && !has_initializer()) {
      Exceptions::ThrowLateFieldNotInitialized(String::Handle(name()));
      UNREACHABLE();
    }
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
#else
    // Our trivial initializer is `null`. Any non-`null` initializer is
    // non-trivial (see `KernelLoader::CheckForInitializer()`).
    value = Object::null();
#endif
  }
  ASSERT(value.IsNull() || value.IsInstance());
  if (is_late() && is_final() &&
      (instance.GetField(*this) != Object::sentinel().ptr())) {
    Exceptions::ThrowLateFieldAssignedDuringInitialization(
        String::Handle(name()));
    UNREACHABLE();
  }
  instance.SetField(*this, value);
  return Error::null();
}

ErrorPtr Field::InitializeStatic() const {
  ASSERT(IsOriginal());
  ASSERT(is_static());
  if (StaticValue() == Object::sentinel().ptr()) {
    ASSERT(is_late());
    auto& value = Object::Handle();
    if (!has_initializer()) {
      Exceptions::ThrowLateFieldNotInitialized(String::Handle(name()));
      UNREACHABLE();
    }
    value = EvaluateInitializer();
    if (value.IsError()) {
      return Error::Cast(value).ptr();
    }
    if (is_final() && (StaticValue() != Object::sentinel().ptr())) {
      Exceptions::ThrowLateFieldAssignedDuringInitialization(
          String::Handle(name()));
      UNREACHABLE();
    }
    ASSERT(value.IsNull() || value.IsInstance());
    SetStaticValue(value.IsNull() ? Instance::null_instance()
                                  : Instance::Cast(value));
    return Error::null();
  }
  return Error::null();
}

ObjectPtr Field::StaticConstFieldValue() const {
  ASSERT(is_static() &&
         (is_const() || (is_final() && has_trivial_initializer())));

  auto thread = Thread::Current();
  auto zone = thread->zone();
  auto initial_field_table =
      is_shared() ? thread->isolate_group()->shared_initial_field_table()
                  : thread->isolate_group()->initial_field_table();

  // We can safely cache the value of the static const field in the initial
  // field table.
  auto& value = Object::Handle(
      zone, initial_field_table->At(field_id(), /*concurrent_use=*/true));
  if (value.ptr() == Object::sentinel().ptr()) {
    // Fields with trivial initializers get their initial value
    // eagerly when they are registered.
    ASSERT(is_const());
    ASSERT(has_initializer());
    ASSERT(has_nontrivial_initializer());
    value = EvaluateInitializer();
    if (!value.IsError()) {
      ASSERT(value.IsNull() || value.IsInstance());
      SetStaticConstFieldValue(value.IsNull() ? Instance::null_instance()
                                              : Instance::Cast(value));
    }
  }
  return value.ptr();
}

void Field::SetStaticConstFieldValue(const Instance& value,
                                     bool assert_initializing_store) const {
  ASSERT(is_static());
  auto thread = Thread::Current();
  auto initial_field_table =
      is_shared() ? thread->isolate_group()->shared_initial_field_table()
                  : thread->isolate_group()->initial_field_table();

  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
  ASSERT(initial_field_table->At(field_id()) == Object::sentinel().ptr() ||
         initial_field_table->At(field_id()) == value.ptr() ||
         !assert_initializing_store);
  initial_field_table->SetAt(field_id(),
                             value.IsNull() ? Instance::null_instance().ptr()
                                            : Instance::Cast(value).ptr(),
                             /*concurrent_use=*/true);
}

ObjectPtr Field::EvaluateInitializer() const {
  ASSERT(Thread::Current()->IsDartMutatorThread());

#if !defined(DART_PRECOMPILED_RUNTIME)
  if (is_static() && is_const()) {
#if defined(DART_DYNAMIC_MODULES)
    if (is_declared_in_bytecode()) {
      const auto& initializer = Function::Handle(InitializerFunction());
      ASSERT(!initializer.IsNull());
      const auto& bytecode = Bytecode::Handle(initializer.GetBytecode());
      ASSERT(!bytecode.IsNull());
      const auto& pool = ObjectPool::Handle(bytecode.object_pool());
      ASSERT(!pool.IsNull());
      ASSERT(pool.Length() == 1);
      return pool.ObjectAt(0);
    }
#endif  // defined(DART_DYNAMIC_MODULES)
    return kernel::EvaluateStaticConstFieldInitializer(*this);
  }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

  const Function& initializer = Function::Handle(EnsureInitializerFunction());
  return DartEntry::InvokeFunction(initializer, Object::empty_array());
}

static intptr_t GetListLength(const Object& value) {
  if (value.IsTypedDataBase()) {
    return TypedDataBase::Cast(value).Length();
  } else if (value.IsArray()) {
    return Array::Cast(value).Length();
  } else if (value.IsGrowableObjectArray()) {
    // List length is variable.
    return Field::kNoFixedLength;
  }
  return Field::kNoFixedLength;
}

static intptr_t GetListLengthOffset(intptr_t cid) {
  if (IsTypedDataClassId(cid) || IsTypedDataViewClassId(cid) ||
      IsUnmodifiableTypedDataViewClassId(cid) ||
      IsExternalTypedDataClassId(cid)) {
    return TypedData::length_offset();
  } else if (cid == kArrayCid || cid == kImmutableArrayCid) {
    return Array::length_offset();
  } else if (cid == kGrowableObjectArrayCid) {
    // List length is variable.
    return Field::kUnknownLengthOffset;
  }
  return Field::kUnknownLengthOffset;
}

const char* Field::GuardedPropertiesAsCString() const {
  if (guarded_cid() == kIllegalCid) {
    return "<?>";
  } else if (guarded_cid() == kDynamicCid) {
    ASSERT(!static_type_exactness_state().IsExactOrUninitialized());
    return "<*>";
  }

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

  const char* exactness = "";
  if (static_type_exactness_state().IsTracking()) {
    exactness =
        zone->PrintToString(" {%s}", static_type_exactness_state().ToCString());
  }

  const Class& cls =
      Class::Handle(IsolateGroup::Current()->class_table()->At(guarded_cid()));
  const char* class_name = String::Handle(cls.Name()).ToCString();

  if (IsBuiltinListClassId(guarded_cid()) && !is_nullable() && is_final()) {
    ASSERT(guarded_list_length() != kUnknownFixedLength);
    if (guarded_list_length() == kNoFixedLength) {
      return zone->PrintToString("<%s [*]%s>", class_name, exactness);
    } else {
      return zone->PrintToString(
          "<%s [%" Pd " @%" Pd "]%s>", class_name, guarded_list_length(),
          guarded_list_length_in_object_offset(), exactness);
    }
  }

  return zone->PrintToString("<%s %s%s>",
                             is_nullable() ? "nullable" : "not-nullable",
                             class_name, exactness);
}

void Field::InitializeGuardedListLengthInObjectOffset(bool unsafe) const {
  auto setter = unsafe ? &Field::set_guarded_list_length_in_object_offset_unsafe
                       : &Field::set_guarded_list_length_in_object_offset;
  ASSERT(IsOriginal());
  if (needs_length_check() &&
      (guarded_list_length() != Field::kUnknownFixedLength)) {
    const intptr_t offset = GetListLengthOffset(guarded_cid());
    (this->*setter)(offset);
    ASSERT(offset != Field::kUnknownLengthOffset);
  } else {
    (this->*setter)(Field::kUnknownLengthOffset);
  }
}

class FieldGuardUpdater {
 public:
  FieldGuardUpdater(const Field* field, const Object& value);

  bool IsUpdateNeeded() {
    return does_guarded_cid_need_update_ || does_is_nullable_need_update_ ||
           does_list_length_and_offset_need_update_ ||
           does_static_type_exactness_state_need_update_;
  }
  void DoUpdate();

 private:
  void ReviewExactnessState();
  void ReviewGuards();

  intptr_t guarded_cid() { return guarded_cid_; }
  void set_guarded_cid(intptr_t guarded_cid) {
    guarded_cid_ = guarded_cid;
    does_guarded_cid_need_update_ = true;
  }

  bool is_nullable() { return is_nullable_; }
  void set_is_nullable(bool is_nullable) {
    is_nullable_ = is_nullable;
    does_is_nullable_need_update_ = true;
  }

  intptr_t guarded_list_length() { return list_length_; }
  void set_guarded_list_length_and_offset(
      intptr_t list_length,
      intptr_t list_length_in_object_offset) {
    list_length_ = list_length;
    list_length_in_object_offset_ = list_length_in_object_offset;
    does_list_length_and_offset_need_update_ = true;
  }

  StaticTypeExactnessState static_type_exactness_state() {
    return static_type_exactness_state_;
  }
  void set_static_type_exactness_state(StaticTypeExactnessState state) {
    static_type_exactness_state_ = state;
    does_static_type_exactness_state_need_update_ = true;
  }

  const Field* field_;
  const Object& value_;

  intptr_t guarded_cid_;
  bool is_nullable_;
  intptr_t list_length_;
  intptr_t list_length_in_object_offset_;
  StaticTypeExactnessState static_type_exactness_state_;

  bool does_guarded_cid_need_update_ = false;
  bool does_is_nullable_need_update_ = false;
  bool does_list_length_and_offset_need_update_ = false;
  bool does_static_type_exactness_state_need_update_ = false;
};

void FieldGuardUpdater::ReviewGuards() {
  ASSERT(field_->IsOriginal());
  const intptr_t cid = value_.GetClassId();

  if (guarded_cid() == kIllegalCid) {
    set_guarded_cid(cid);
    set_is_nullable(cid == kNullCid);

    // Start tracking length if needed.
    ASSERT((guarded_list_length() == Field::kUnknownFixedLength) ||
           (guarded_list_length() == Field::kNoFixedLength));
    if (field_->needs_length_check()) {
      ASSERT(guarded_list_length() == Field::kUnknownFixedLength);
      set_guarded_list_length_and_offset(GetListLength(value_),
                                         GetListLengthOffset(cid));
    }

    if (FLAG_trace_field_guards) {
      THR_Print("    => %s\n", field_->GuardedPropertiesAsCString());
    }
    return;
  }

  if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) {
    // Class id of the assigned value matches expected class id and nullability.

    // If we are tracking length check if it has matches.
    if (field_->needs_length_check() &&
        (guarded_list_length() != GetListLength(value_))) {
      ASSERT(guarded_list_length() != Field::kUnknownFixedLength);
      set_guarded_list_length_and_offset(Field::kNoFixedLength,
                                         Field::kUnknownLengthOffset);
      return;
    }

    // Everything matches.
    return;
  }

  if ((cid == kNullCid) && !is_nullable()) {
    // Assigning null value to a non-nullable field makes it nullable.
    set_is_nullable(true);
  } else if ((cid != kNullCid) && (guarded_cid() == kNullCid)) {
    // Assigning non-null value to a field that previously contained only null
    // turns it into a nullable field with the given class id.
    ASSERT(is_nullable());
    set_guarded_cid(cid);
  } else {
    // Give up on tracking class id of values contained in this field.
    ASSERT(guarded_cid() != cid);
    set_guarded_cid(kDynamicCid);
    set_is_nullable(true);
  }

  // If we were tracking length drop collected feedback.
  if (field_->needs_length_check()) {
    ASSERT(guarded_list_length() != Field::kUnknownFixedLength);
    set_guarded_list_length_and_offset(Field::kNoFixedLength,
                                       Field::kUnknownLengthOffset);
  }
}

bool Class::FindInstantiationOf(Zone* zone,
                                const Class& cls,
                                GrowableArray<const Type*>* path,
                                bool consider_only_super_classes) const {
  ASSERT(cls.is_type_finalized());
  if (cls.ptr() == ptr()) {
    return true;  // Found instantiation.
  }

  Class& cls2 = Class::Handle(zone);
  Type& super = Type::Handle(zone, super_type());
  if (!super.IsNull() && !super.IsObjectType()) {
    cls2 = super.type_class();
    if (path != nullptr) {
      path->Add(&super);
    }
    if (cls2.FindInstantiationOf(zone, cls, path,
                                 consider_only_super_classes)) {
      return true;  // Found instantiation.
    }
    if (path != nullptr) {
      path->RemoveLast();
    }
  }

  if (!consider_only_super_classes) {
    Array& super_interfaces = Array::Handle(zone, interfaces());
    for (intptr_t i = 0; i < super_interfaces.Length(); i++) {
      super ^= super_interfaces.At(i);
      cls2 = super.type_class();
      if (path != nullptr) {
        path->Add(&super);
      }
      if (cls2.FindInstantiationOf(zone, cls, path)) {
        return true;  // Found instantiation.
      }
      if (path != nullptr) {
        path->RemoveLast();
      }
    }
  }

  return false;  // Not found.
}

bool Class::FindInstantiationOf(Zone* zone,
                                const Type& type,
                                GrowableArray<const Type*>* path,
                                bool consider_only_super_classes) const {
  return FindInstantiationOf(zone, Class::Handle(zone, type.type_class()), path,
                             consider_only_super_classes);
}

TypePtr Class::GetInstantiationOf(Zone* zone, const Class& cls) const {
  if (ptr() == cls.ptr()) {
    return DeclarationType();
  }
  if (FindInstantiationOf(zone, cls, /*consider_only_super_classes=*/true)) {
    // Since [cls] is a superclass of [this], use [cls]'s declaration type.
    return cls.DeclarationType();
  }
  const auto& decl_type = Type::Handle(zone, DeclarationType());
  GrowableArray<const Type*> path(zone, 0);
  if (!FindInstantiationOf(zone, cls, &path)) {
    return Type::null();
  }
  Thread* thread = Thread::Current();
  ASSERT(!path.is_empty());
  auto& calculated_type = Type::Handle(zone, decl_type.ptr());
  auto& calculated_type_class =
      Class::Handle(zone, calculated_type.type_class());
  auto& calculated_type_args =
      TypeArguments::Handle(zone, calculated_type.arguments());
  calculated_type_args = calculated_type_args.ToInstantiatorTypeArguments(
      thread, calculated_type_class);
  for (auto* const type : path) {
    calculated_type ^= type->ptr();
    if (!calculated_type.IsInstantiated()) {
      calculated_type ^= calculated_type.InstantiateFrom(
          calculated_type_args, Object::null_type_arguments(), kAllFree,
          Heap::kNew);
    }
    calculated_type_class = calculated_type.type_class();
    calculated_type_args = calculated_type.arguments();
    calculated_type_args = calculated_type_args.ToInstantiatorTypeArguments(
        thread, calculated_type_class);
  }
  ASSERT_EQUAL(calculated_type.type_class_id(), cls.id());
  return calculated_type.ptr();
}

TypePtr Class::GetInstantiationOf(Zone* zone, const Type& type) const {
  return GetInstantiationOf(zone, Class::Handle(zone, type.type_class()));
}

void Field::SetStaticValue(const Object& value) const {
  auto thread = Thread::Current();
  ASSERT(thread->IsDartMutatorThread());
  ASSERT(value.IsNull() || value.IsSentinel() || value.IsInstance());

  ASSERT(is_static());  // Valid only for static dart fields.
  const intptr_t id = field_id();
  ASSERT(id >= 0);

  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
  if (is_shared()) {
    thread->isolate_group()->shared_field_table()->SetAt(id, value.ptr());
  } else {
    thread->isolate()->field_table()->SetAt(id, value.ptr());
  }
}

static StaticTypeExactnessState TrivialTypeExactnessFor(const Class& cls) {
  const intptr_t type_arguments_offset = cls.host_type_arguments_field_offset();
  ASSERT(type_arguments_offset != Class::kNoTypeArguments);
  if (StaticTypeExactnessState::CanRepresentAsTriviallyExact(
          type_arguments_offset / kCompressedWordSize)) {
    return StaticTypeExactnessState::TriviallyExact(type_arguments_offset /
                                                    kCompressedWordSize);
  } else {
    return StaticTypeExactnessState::NotExact();
  }
}

static const char* SafeTypeArgumentsToCString(const TypeArguments& args) {
  return (args.ptr() == TypeArguments::null()) ? "<null>" : args.ToCString();
}

StaticTypeExactnessState StaticTypeExactnessState::Compute(
    const Type& static_type,
    const Instance& value,
    bool print_trace /* = false */) {
  ASSERT(!value.IsNull());  // Should be handled by the caller.
  ASSERT(value.ptr() != Object::sentinel().ptr());

  Thread* thread = Thread::Current();
  Zone* const zone = thread->zone();
  const TypeArguments& static_type_args =
      TypeArguments::Handle(zone, static_type.GetInstanceTypeArguments(thread));

  TypeArguments& args = TypeArguments::Handle(zone);

  ASSERT(static_type.IsFinalized());
  const Class& cls = Class::Handle(zone, value.clazz());
  GrowableArray<const Type*> path(10);

  bool is_super_class = true;
  if (!cls.FindInstantiationOf(zone, static_type, &path,
                               /*consider_only_super_classes=*/true)) {
    is_super_class = false;
    bool found_super_interface =
        cls.FindInstantiationOf(zone, static_type, &path);
    ASSERT(found_super_interface);
  }

  // Trivial case: field has type G<T0, ..., Tn> and value has type
  // G<U0, ..., Un>. Check if type arguments match.
  if (path.is_empty()) {
    ASSERT(cls.ptr() == static_type.type_class());
    args = value.GetTypeArguments();
    // TODO(dartbug.com/34170) Evaluate if comparing relevant subvectors (that
    // disregards superclass own arguments) improves precision of the
    // tracking.
    if (args.ptr() == static_type_args.ptr()) {
      return TrivialTypeExactnessFor(cls);
    }

    if (print_trace) {
      THR_Print("  expected %s got %s type arguments\n",
                SafeTypeArgumentsToCString(static_type_args),
                SafeTypeArgumentsToCString(args));
    }
    return StaticTypeExactnessState::NotExact();
  }

  // Value has type C<U0, ..., Un> and field has type G<T0, ..., Tn> and G != C.
  // Compute C<X0, ..., Xn> at G (Xi are free type arguments).
  // Path array contains a chain of immediate supertypes S0 <: S1 <: ... Sn,
  // such that S0 is an immediate supertype of C and Sn is G<...>.
  // Each Si might depend on type parameters of the previous supertype S{i-1}.
  // To compute C<X0, ..., Xn> at G we walk the chain backwards and
  // instantiate Si using type parameters of S{i-1} which gives us a type
  // depending on type parameters of S{i-2}.
  Type& type = Type::Handle(zone, path.Last()->ptr());
  for (intptr_t i = path.length() - 2; (i >= 0) && !type.IsInstantiated();
       i--) {
    args = path[i]->GetInstanceTypeArguments(thread, /*canonicalize=*/false);
    type ^= type.InstantiateFrom(args, TypeArguments::null_type_arguments(),
                                 kAllFree, Heap::kNew);
  }

  if (type.IsInstantiated()) {
    // C<X0, ..., Xn> at G is fully instantiated and does not depend on
    // Xi. In this case just check if type arguments match.
    args = type.GetInstanceTypeArguments(thread, /*canonicalize=*/false);
    if (args.Equals(static_type_args)) {
      return is_super_class ? StaticTypeExactnessState::HasExactSuperClass()
                            : StaticTypeExactnessState::HasExactSuperType();
    }

    if (print_trace) {
      THR_Print("  expected %s got %s type arguments\n",
                SafeTypeArgumentsToCString(static_type_args),
                SafeTypeArgumentsToCString(args));
    }

    return StaticTypeExactnessState::NotExact();
  }

  // The most complicated case: C<X0, ..., Xn> at G depends on
  // Xi values. To compare type arguments we would need to instantiate
  // it fully from value's type arguments and compare with <U0, ..., Un>.
  // However this would complicate fast path in the native code. To avoid this
  // complication we would optimize for the trivial case: we check if
  // C<X0, ..., Xn> at G is exactly G<X0, ..., Xn> which means we can simply
  // compare values type arguments (<T0, ..., Tn>) to fields type arguments
  // (<U0, ..., Un>) to establish if field type is exact.
  ASSERT(cls.IsGeneric());
  const intptr_t num_type_params = cls.NumTypeParameters();
  bool trivial_case =
      (num_type_params ==
       Class::Handle(zone, static_type.type_class()).NumTypeParameters()) &&
      (value.GetTypeArguments() == static_type_args.ptr());
  if (!trivial_case && FLAG_trace_field_guards) {
    THR_Print("Not a simple case: %" Pd " vs %" Pd
              " type parameters, %s vs %s type arguments\n",
              num_type_params,
              Class::Handle(zone, static_type.type_class()).NumTypeParameters(),
              SafeTypeArgumentsToCString(
                  TypeArguments::Handle(zone, value.GetTypeArguments())),
              SafeTypeArgumentsToCString(static_type_args));
  }

  AbstractType& type_arg = AbstractType::Handle(zone);
  args = type.GetInstanceTypeArguments(thread, /*canonicalize=*/false);
  for (intptr_t i = 0; (i < num_type_params) && trivial_case; i++) {
    type_arg = args.TypeAt(i);
    if (!type_arg.IsTypeParameter() ||
        (TypeParameter::Cast(type_arg).index() != i)) {
      if (FLAG_trace_field_guards) {
        THR_Print("  => encountered %s at index % " Pd "\n",
                  type_arg.ToCString(), i);
      }
      trivial_case = false;
    }
  }

  return trivial_case ? TrivialTypeExactnessFor(cls)
                      : StaticTypeExactnessState::NotExact();
}

const char* StaticTypeExactnessState::ToCString() const {
  if (!IsTracking()) {
    return "not-tracking";
  } else if (!IsExactOrUninitialized()) {
    return "not-exact";
  } else if (IsTriviallyExact()) {
    return Thread::Current()->zone()->PrintToString(
        "trivially-exact(%hhu)", GetTypeArgumentsOffsetInWords());
  } else if (IsHasExactSuperType()) {
    return "has-exact-super-type";
  } else if (IsHasExactSuperClass()) {
    return "has-exact-super-class";
  } else {
    ASSERT(IsUninitialized());
    return "uninitialized-exactness";
  }
}

void FieldGuardUpdater::ReviewExactnessState() {
  if (!static_type_exactness_state().IsExactOrUninitialized()) {
    // Nothing to update.
    return;
  }

  if (guarded_cid() == kDynamicCid) {
    if (FLAG_trace_field_guards) {
      THR_Print(
          "  => switching off exactness tracking because guarded cid is "
          "dynamic\n");
    }
    set_static_type_exactness_state(StaticTypeExactnessState::NotExact());
    return;
  }

  // If we are storing null into a field or we have an exact super type
  // then there is nothing to do.
  if (value_.IsNull() || static_type_exactness_state().IsHasExactSuperType() ||
      static_type_exactness_state().IsHasExactSuperClass()) {
    return;
  }

  // If we are storing a non-null value into a field that is considered
  // to be trivially exact then we need to check if value has an appropriate
  // type.
  ASSERT(guarded_cid() != kNullCid);

  const Type& field_type = Type::Cast(AbstractType::Handle(field_->type()));
  const Instance& instance = Instance::Cast(value_);

  if (static_type_exactness_state().IsTriviallyExact()) {
    const TypeArguments& args =
        TypeArguments::Handle(instance.GetTypeArguments());
    const TypeArguments& field_type_args = TypeArguments::Handle(
        field_type.GetInstanceTypeArguments(Thread::Current()));
    if (args.ptr() == field_type_args.ptr()) {
      return;
    }

    if (FLAG_trace_field_guards) {
      THR_Print("  expected %s got %s type arguments\n",
                field_type_args.ToCString(), args.ToCString());
    }

    set_static_type_exactness_state(StaticTypeExactnessState::NotExact());
    return;
  }

  ASSERT(static_type_exactness_state().IsUninitialized());
  set_static_type_exactness_state(StaticTypeExactnessState::Compute(
      field_type, instance, FLAG_trace_field_guards));
  return;
}

FieldGuardUpdater::FieldGuardUpdater(const Field* field, const Object& value)
    : field_(field),
      value_(value),
      guarded_cid_(field->guarded_cid()),
      is_nullable_(field->is_nullable()),
      list_length_(field->guarded_list_length()),
      list_length_in_object_offset_(
          field->guarded_list_length_in_object_offset()),
      static_type_exactness_state_(field->static_type_exactness_state()) {
  ReviewGuards();
  ReviewExactnessState();
}

void FieldGuardUpdater::DoUpdate() {
  if (does_guarded_cid_need_update_) {
    field_->set_guarded_cid(guarded_cid_);
  }
  if (does_is_nullable_need_update_) {
    field_->set_is_nullable(is_nullable_);
  }
  if (does_list_length_and_offset_need_update_) {
    field_->set_guarded_list_length(list_length_);
    field_->set_guarded_list_length_in_object_offset(
        list_length_in_object_offset_);
  }
  if (does_static_type_exactness_state_need_update_) {
    field_->set_static_type_exactness_state(static_type_exactness_state_);
  }
}

void Field::RecordStore(const Object& value) const {
  ASSERT(IsOriginal());
  Thread* const thread = Thread::Current();
  if (!thread->isolate_group()->use_field_guards()) {
    return;
  }

  // We should never try to record a sentinel.
  ASSERT(value.ptr() != Object::sentinel().ptr());

  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
  if ((guarded_cid() == kDynamicCid) ||
      (is_nullable() && value.ptr() == Object::null())) {
    // Nothing to do: the field is not guarded or we are storing null into
    // a nullable field.
    return;
  }

  if (FLAG_trace_field_guards) {
    THR_Print("Store %s %s <- %s\n", ToCString(), GuardedPropertiesAsCString(),
              value.ToCString());
  }

  FieldGuardUpdater updater(this, value);
  if (updater.IsUpdateNeeded()) {
    if (FLAG_trace_field_guards) {
      THR_Print("    => %s\n", GuardedPropertiesAsCString());
    }
    // Nobody else could have updated guard state since we are holding write
    // program lock. But we need to ensure we stop mutators as we update
    // guard state as we can't have optimized code running with updated fields.
    auto isolate_group = IsolateGroup::Current();
    isolate_group->RunWithStoppedMutators([&]() {
      updater.DoUpdate();
      DeoptimizeDependentCode(/*are_mutators_stopped=*/true);
    });
  }
}

void Field::ForceDynamicGuardedCidAndLength() const {
  if (!is_unboxed()) {
    set_guarded_cid(kDynamicCid);
    set_is_nullable(true);
  }
  set_guarded_list_length(Field::kNoFixedLength);
  set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
  if (static_type_exactness_state().IsTracking()) {
    set_static_type_exactness_state(StaticTypeExactnessState::NotExact());
  }
  // Drop any code that relied on the above assumptions.
  DeoptimizeDependentCode();
}

StringPtr Script::resolved_url() const {
#if defined(DART_PRECOMPILER)
  return String::RawCast(
      WeakSerializationReference::Unwrap(untag()->resolved_url()));
#else
  return untag()->resolved_url();
#endif
}

bool Script::HasSource() const {
  return untag()->source() != String::null();
}

StringPtr Script::Source() const {
  return untag()->source();
}

bool Script::IsPartOfDartColonLibrary() const {
  const String& script_url = String::Handle(url());
  return (script_url.StartsWith(Symbols::DartScheme()) ||
          script_url.StartsWith(Symbols::DartSchemePrivate()));
}

#if !defined(DART_PRECOMPILED_RUNTIME)
void Script::LoadSourceFromKernel(const uint8_t* kernel_buffer,
                                  intptr_t kernel_buffer_len) const {
  String& uri = String::Handle(resolved_url());
  String& source = String::Handle(kernel::KernelLoader::FindSourceForScript(
      kernel_buffer, kernel_buffer_len, uri));
  set_source(source);
}

void Script::InitializeFromKernel(
    const KernelProgramInfo& info,
    intptr_t script_index,
    const TypedData& line_starts,
    const TypedDataView& constant_coverage) const {
  StoreNonPointer(&untag()->kernel_script_index_, script_index);
  untag()->set_kernel_program_info(info.ptr());
  untag()->set_line_starts(line_starts.ptr());
  untag()->set_debug_positions(Array::null_array().ptr());
  NOT_IN_PRODUCT(untag()->set_constant_coverage(constant_coverage.ptr()));
}
#endif

GrowableObjectArrayPtr Script::GenerateLineNumberArray() const {
  Zone* zone = Thread::Current()->zone();
  const GrowableObjectArray& info =
      GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
  const Object& line_separator = Object::Handle(zone);
  if (line_starts() == TypedData::null()) {
    // Scripts in the AOT snapshot do not have a line starts array.
    // A well-formed line number array has a leading null.
    info.Add(line_separator);  // New line.
    return info.ptr();
  }
#if !defined(DART_PRECOMPILED_RUNTIME)
  Smi& value = Smi::Handle(zone);
  const TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
  intptr_t line_count = line_starts_data.Length();
  const Array& debug_positions_array = Array::Handle(debug_positions());
  ASSERT(!debug_positions_array.IsNull());
  intptr_t token_count = debug_positions_array.Length();
  int token_index = 0;

  LineStartsReader line_starts_reader(line_starts_data);
  for (int line_index = 0; line_index < line_count; ++line_index) {
    intptr_t start = line_starts_reader.At(line_index);
    // Output the rest of the tokens if we have no next line.
    intptr_t end = TokenPosition::kMaxSourcePos;
    if (line_index + 1 < line_count) {
      end = line_starts_reader.At(line_index + 1);
    }
    bool first = true;
    while (token_index < token_count) {
      value ^= debug_positions_array.At(token_index);
      intptr_t debug_position = value.Value();
      if (debug_position >= end) break;

      if (first) {
        info.Add(line_separator);          // New line.
        value = Smi::New(line_index + 1);  // Line number.
        info.Add(value);
        first = false;
      }

      value ^= debug_positions_array.At(token_index);
      info.Add(value);                               // Token position.
      value = Smi::New(debug_position - start + 1);  // Column.
      info.Add(value);
      ++token_index;
    }
  }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  return info.ptr();
}

TokenPosition Script::MaxPosition() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (HasCachedMaxPosition()) {
    return TokenPosition::Deserialize(
        UntaggedScript::CachedMaxPositionBitField::decode(
            untag()->flags_and_max_position_));
  }
  if (!HasCachedMaxPosition() && line_starts() != TypedData::null()) {
    auto const zone = Thread::Current()->zone();
    const auto& starts = TypedData::Handle(zone, line_starts());
    LineStartsReader reader(starts);
    const intptr_t max_position = reader.MaxPosition();
    SetCachedMaxPosition(max_position);
    SetHasCachedMaxPosition(true);
    return TokenPosition::Deserialize(max_position);
  }
#endif
  return TokenPosition::kNoSource;
}

void Script::set_url(const String& value) const {
  untag()->set_url(value.ptr());
}

void Script::set_resolved_url(const String& value) const {
  untag()->set_resolved_url(value.ptr());
}

void Script::set_source(const String& value) const {
  untag()->set_source(value.ptr());
}

#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
TypedDataViewPtr Script::constant_coverage() const {
  return untag()->constant_coverage();
}
#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

TypedDataPtr Script::line_starts() const {
  return untag()->line_starts();
}

void Script::set_line_starts(const TypedData& value) const {
  untag()->set_line_starts(value.ptr());
}

#if !defined(DART_PRECOMPILED_RUNTIME)

static int LowestFirst(const intptr_t* a, const intptr_t* b) {
  return *a - *b;
}

static ArrayPtr SortAndDeduplicate(GrowableArray<intptr_t>* source) {
  intptr_t size = source->length();
  if (size == 0) {
    return Object::empty_array().ptr();
  }

  source->Sort(LowestFirst);

  intptr_t last = 0;
  for (intptr_t current = 1; current < size; ++current) {
    if (source->At(last) != source->At(current)) {
      (*source)[++last] = source->At(current);
    }
  }
  Array& array_object = Array::Handle();
  array_object = Array::New(last + 1, Heap::kOld);
  Smi& smi_value = Smi::Handle();
  for (intptr_t i = 0; i <= last; ++i) {
    smi_value = Smi::New(source->At(i));
    array_object.SetAt(i, smi_value);
  }
  return array_object.ptr();
}

void Script::CollectDebugTokenPositions() const {
  GrowableArray<intptr_t> token_positions(10);
  if (kernel_program_info() != Object::null()) {
    kernel::CollectScriptTokenPositionsFromKernel(*this, &token_positions);
  } else {
#if defined(DART_DYNAMIC_MODULES)
    bytecode::BytecodeReader::CollectScriptTokenPositionsFromBytecode(
        *this, &token_positions);
#else
    UNREACHABLE();
#endif
  }
  const auto& debug_positions =
      Array::Handle(SortAndDeduplicate(&token_positions));
  set_debug_positions(debug_positions);
}

#endif  // !defined(DART_PRECOMPILED_RUNTIME)

ArrayPtr Script::debug_positions() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
  Array& debug_positions_array = Array::Handle(untag()->debug_positions());
  if (debug_positions_array.IsNull()) {
    // This is created lazily. Now we need it.
    CollectDebugTokenPositions();
  }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  return untag()->debug_positions();
}

void Script::set_debug_positions(const Array& value) const {
  untag()->set_debug_positions(value.ptr());
}

#if !defined(DART_PRECOMPILED_RUNTIME)
bool Script::HasCachedMaxPosition() const {
  return UntaggedScript::HasCachedMaxPositionBit::decode(
      untag()->flags_and_max_position_);
}

void Script::SetHasCachedMaxPosition(bool value) const {
  StoreNonPointer(&untag()->flags_and_max_position_,
                  UntaggedScript::HasCachedMaxPositionBit::update(
                      value, untag()->flags_and_max_position_));
}

void Script::SetCachedMaxPosition(intptr_t value) const {
  StoreNonPointer(&untag()->flags_and_max_position_,
                  UntaggedScript::CachedMaxPositionBitField::update(
                      value, untag()->flags_and_max_position_));
}
#endif

void Script::set_load_timestamp(int64_t value) const {
  StoreNonPointer(&untag()->load_timestamp_, value);
}

bool Script::IsValidTokenPosition(TokenPosition token_pos) const {
  const TokenPosition& max_position = MaxPosition();
  // We may end up with scripts that have the empty string as a source file
  // in testing and the like, so allow any token position when the max position
  // is 0 as well as when it is kNoSource.
  return !max_position.IsReal() || !token_pos.IsReal() ||
         max_position.Pos() == 0 || token_pos <= max_position;
}

#if !defined(DART_PRECOMPILED_RUNTIME)
static bool IsLetter(int32_t c) {
  return (('A' <= c) && (c <= 'Z')) || (('a' <= c) && (c <= 'z'));
}

static bool IsDecimalDigit(int32_t c) {
  return '0' <= c && c <= '9';
}

static bool IsIdentStartChar(int32_t c) {
  return IsLetter(c) || (c == '_') || (c == '$');
}

static bool IsIdentChar(int32_t c) {
  return IsLetter(c) || IsDecimalDigit(c) || (c == '_') || (c == '$');
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

bool Script::GetTokenLocation(const TokenPosition& token_pos,
                              intptr_t* line,
                              intptr_t* column) const {
  ASSERT(line != nullptr);
#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES)
  // Scripts in the AOT snapshot do not have a line starts array.
  return false;
#else
  if (!token_pos.IsReal()) return false;

  auto const zone = Thread::Current()->zone();
  const TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
  if (line_starts_data.IsNull()) return false;
  LineStartsReader line_starts_reader(line_starts_data);
  return line_starts_reader.LocationForPosition(token_pos.Pos(), line, column);
#endif  // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES)
}

intptr_t Script::GetTokenLength(const TokenPosition& token_pos) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  // Scripts in the AOT snapshot do not have their source.
  return -1;
#else
  if (!HasSource() || !token_pos.IsReal()) return -1;
  auto const zone = Thread::Current()->zone();
  // We don't explicitly save this data: Load the source and find it from there.
  const String& source = String::Handle(zone, Source());
  const intptr_t start = token_pos.Pos();
  if (start >= source.Length()) return -1;  // Can't determine token_len.
  intptr_t end = start;
  if (IsIdentStartChar(source.CharAt(end++))) {
    for (; end < source.Length(); ++end) {
      if (!IsIdentChar(source.CharAt(end))) break;
    }
  }
  return end - start;
#endif
}

bool Script::TokenRangeAtLine(intptr_t line_number,
                              TokenPosition* first_token_index,
                              TokenPosition* last_token_index) const {
  ASSERT(first_token_index != nullptr && last_token_index != nullptr);
#if defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES)
  // Scripts in the AOT snapshot do not have a line starts array.
  return false;
#else
  // Line numbers are 1-indexed.
  if (line_number <= 0) return false;
  Zone* zone = Thread::Current()->zone();
  const TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
  if (line_starts_data.IsNull()) return false;
  LineStartsReader line_starts_reader(line_starts_data);
  if (!line_starts_reader.TokenRangeAtLine(line_number, first_token_index,
                                           last_token_index)) {
    return false;
  }
#if defined(DEBUG)
  intptr_t source_length;
  if (!HasSource()) {
    Smi& value = Smi::Handle(zone);
    const Array& debug_positions_array = Array::Handle(zone, debug_positions());
    ASSERT(!debug_positions_array.IsNull());
    value ^= debug_positions_array.At(debug_positions_array.Length() - 1);
    source_length = value.Value();
  } else {
    const String& source = String::Handle(zone, Source());
    source_length = source.Length();
  }
  ASSERT(last_token_index->Serialize() <= source_length);
#endif
  return true;
#endif  // defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_DYNAMIC_MODULES)
}

// Returns the index in the given source string for the given (1-based) absolute
// line and column numbers. The line and column offsets are used to calculate
// the absolute line and column number for the starting index in the source.
//
// If the given line number is outside the range of lines represented by the
// source, the given column number invalid for the given line, or a negative
// starting index is given, a negative value is returned to indicate failure.
static intptr_t GetRelativeSourceIndex(const String& src,
                                       intptr_t line,
                                       intptr_t line_offset = 0,
                                       intptr_t column = 1,
                                       intptr_t column_offset = 0,
                                       intptr_t starting_index = 0) {
  if (starting_index < 0 || line < 1 || column < 1 || line <= line_offset ||
      (line == line_offset + 1 && column <= column_offset)) {
    return -1;
  }
  intptr_t len = src.Length();
  intptr_t current_line = line_offset + 1;
  intptr_t current_index = starting_index;
  for (; current_index < len; current_index++) {
    if (current_line == line) {
      break;
    }
    const uint16_t c = src.CharAt(current_index);
    if (c == '\n' || c == '\r') {
      current_line++;
    }
    if (c == '\r' && current_index + 1 < len &&
        src.CharAt(current_index + 1) == '\n') {
      // \r\n is treated as a single line terminator.
      current_index++;
    }
  }
  if (current_line != line) {
    return -1;
  }
  // Only adjust with column offset when still on the first line.
  intptr_t current_column = 1 + (line == line_offset + 1 ? column_offset : 0);
  for (; current_index < len; current_index++, current_column++) {
    if (current_column == column) {
      return current_index;
    }
    const uint16_t c = src.CharAt(current_index);
    if (c == '\n' || c == '\r') {
      break;
    }
  }
  // Check for a column value representing the source's end.
  if (current_column == column) {
    return current_index;
  }
  return -1;
}

StringPtr Script::GetLine(intptr_t line_number, Heap::Space space) const {
  if (!HasSource()) {
    return Symbols::OptimizedOut().ptr();
  }
  const String& src = String::Handle(Source());
  const intptr_t start =
      GetRelativeSourceIndex(src, line_number, line_offset());
  if (start < 0) {
    return Symbols::Empty().ptr();
  }
  intptr_t end = start;
  for (; end < src.Length(); end++) {
    const uint16_t c = src.CharAt(end);
    if (c == '\n' || c == '\r') {
      break;
    }
  }
  return String::SubString(src, start, end - start, space);
}

StringPtr Script::GetSnippet(intptr_t from_line,
                             intptr_t from_column,
                             intptr_t to_line,
                             intptr_t to_column) const {
  if (!HasSource()) {
    return Symbols::OptimizedOut().ptr();
  }
  const String& src = String::Handle(Source());
  const intptr_t start = GetRelativeSourceIndex(src, from_line, line_offset(),
                                                from_column, col_offset());
  // Lines and columns are 1-based, so need to subtract one to get offsets.
  const intptr_t end = GetRelativeSourceIndex(
      src, to_line, from_line - 1, to_column, from_column - 1, start);
  // Only need to check end, because a negative start results in a negative end.
  if (end < 0) {
    return String::null();
  }
  return String::SubString(src, start, end - start);
}

ScriptPtr Script::New(const String& url, const String& source) {
  return Script::New(url, url, source);
}

ScriptPtr Script::New(const String& url,
                      const String& resolved_url,
                      const String& source) {
  ASSERT(Object::script_class() != Class::null());
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const Script& result =
      Script::Handle(zone, Object::Allocate<Script>(Heap::kOld));
  result.set_url(String::Handle(zone, Symbols::New(thread, url)));
  result.set_resolved_url(
      String::Handle(zone, Symbols::New(thread, resolved_url)));
  result.set_source(source);
  NOT_IN_PRECOMPILED(ASSERT_EQUAL(result.HasCachedMaxPosition(), false));
  ASSERT_EQUAL(result.kernel_script_index(), 0);
  if (FLAG_remove_script_timestamps_for_test) {
    ASSERT_EQUAL(result.load_timestamp(), 0);
  } else {
    result.set_load_timestamp(OS::GetCurrentTimeMillis());
  }
  return result.ptr();
}

const char* Script::ToCString() const {
  const String& name = String::Handle(url());
  return OS::SCreate(Thread::Current()->zone(), "Script(%s)", name.ToCString());
}

LibraryPtr Script::FindLibrary() const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  auto isolate_group = thread->isolate_group();
  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
      zone, isolate_group->object_store()->libraries());
  Library& lib = Library::Handle(zone);
  Array& scripts = Array::Handle(zone);
  for (intptr_t i = 0; i < libs.Length(); i++) {
    lib ^= libs.At(i);
    scripts = lib.LoadedScripts();
    for (intptr_t j = 0; j < scripts.Length(); j++) {
      if (scripts.At(j) == ptr()) {
        return lib.ptr();
      }
    }
  }
  return Library::null();
}

DictionaryIterator::DictionaryIterator(const Library& library)
    : array_(Array::Handle(library.dictionary())),
      // Last element in array is a Smi indicating the number of entries used.
      size_(Array::Handle(library.dictionary()).Length() - 1),
      next_ix_(0) {
  MoveToNextObject();
}

ObjectPtr DictionaryIterator::GetNext() {
  ASSERT(HasNext());
  int ix = next_ix_++;
  MoveToNextObject();
  ASSERT(array_.At(ix) != Object::null());
  return array_.At(ix);
}

void DictionaryIterator::MoveToNextObject() {
  Object& obj = Object::Handle(array_.At(next_ix_));
  while (obj.IsNull() && HasNext()) {
    next_ix_++;
    obj = array_.At(next_ix_);
  }
}

ClassDictionaryIterator::ClassDictionaryIterator(const Library& library,
                                                 IterationKind kind)
    : DictionaryIterator(library),
      toplevel_class_(Class::Handle((kind == kIteratePrivate)
                                        ? library.toplevel_class()
                                        : Class::null())) {
  MoveToNextClass();
}

ClassPtr ClassDictionaryIterator::GetNextClass() {
  ASSERT(HasNext());
  Class& cls = Class::Handle();
  if (next_ix_ < size_) {
    int ix = next_ix_++;
    cls ^= array_.At(ix);
    MoveToNextClass();
    return cls.ptr();
  }
  ASSERT(!toplevel_class_.IsNull());
  cls = toplevel_class_.ptr();
  toplevel_class_ = Class::null();
  return cls.ptr();
}

void ClassDictionaryIterator::MoveToNextClass() {
  Object& obj = Object::Handle();
  while (next_ix_ < size_) {
    obj = array_.At(next_ix_);
    if (obj.IsClass()) {
      return;
    }
    next_ix_++;
  }
}

static void ReportTooManyImports(const Library& lib) {
  const String& url = String::Handle(lib.url());
  Report::MessageF(Report::kError, Script::Handle(lib.LookupScript(url)),
                   TokenPosition::kNoSource, Report::AtLocation,
                   "too many imports in library '%s'", url.ToCString());
  UNREACHABLE();
}

bool Library::IsAnyCoreLibrary() const {
  String& url_str = Thread::Current()->StringHandle();
  url_str = url();
  return url_str.StartsWith(Symbols::DartScheme()) ||
         url_str.StartsWith(Symbols::DartSchemePrivate());
}

void Library::set_num_imports(intptr_t value) const {
  if (!Utils::IsUint(16, value)) {
    ReportTooManyImports(*this);
  }
  StoreNonPointer(&untag()->num_imports_, value);
}

void Library::set_name(const String& name) const {
  ASSERT(name.IsSymbol());
  untag()->set_name(name.ptr());
}

void Library::set_url(const String& url) const {
  untag()->set_url(url.ptr());
}

void Library::set_private_key(const String& key) const {
  untag()->set_private_key(key.ptr());
}

#if !defined(DART_PRECOMPILED_RUNTIME)
void Library::set_kernel_program_info(const KernelProgramInfo& info) const {
  untag()->set_kernel_program_info(info.ptr());
}

TypedDataViewPtr Library::KernelLibrary() const {
  const auto& info = KernelProgramInfo::Handle(kernel_program_info());
  return info.KernelLibrary(kernel_library_index());
}

intptr_t Library::KernelLibraryOffset() const {
  const auto& info = KernelProgramInfo::Handle(kernel_program_info());
  return info.KernelLibraryStartOffset(kernel_library_index());
}
#endif

void Library::set_loading_unit(const LoadingUnit& value) const {
  untag()->set_loading_unit(value.ptr());
}

void Library::SetName(const String& name) const {
  // Only set name once.
  ASSERT(!Loaded());
  set_name(name);
}

void Library::SetLoadInProgress() const {
  // Must not already be in the process of being loaded.
  ASSERT(untag()->load_state_ <= UntaggedLibrary::kLoadRequested);
  StoreNonPointer(&untag()->load_state_, UntaggedLibrary::kLoadInProgress);
}

void Library::SetLoadRequested() const {
  // Must not be already loaded.
  ASSERT(untag()->load_state_ == UntaggedLibrary::kAllocated);
  StoreNonPointer(&untag()->load_state_, UntaggedLibrary::kLoadRequested);
}

void Library::SetLoaded() const {
  // Should not be already loaded or just allocated.
  ASSERT(LoadInProgress() || LoadRequested());
  StoreNonPointer(&untag()->load_state_, UntaggedLibrary::kLoaded);
}

void Library::AddMetadata(const Object& declaration,
                          intptr_t kernel_offset) const {
  AddMetadata(declaration, Smi::Handle(Smi::New(kernel_offset)));
}

void Library::AddMetadata(const Object& declaration,
                          const Object& metadata_value) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  Thread* thread = Thread::Current();
  ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());

  MetadataMap map(metadata());
  map.UpdateOrInsert(declaration, metadata_value);
  set_metadata(map.Release());
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

ObjectPtr Library::GetMetadata(const Object& declaration) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  return Object::empty_array().ptr();
#else
  RELEASE_ASSERT(declaration.IsClass() || declaration.IsField() ||
                 declaration.IsFunction() || declaration.IsLibrary() ||
                 declaration.IsTypeParameter() || declaration.IsNamespace());

  auto thread = Thread::Current();
  auto zone = thread->zone();

  if (declaration.IsLibrary()) {
    // Ensure top-level class is loaded as it may contain annotations of
    // a library.
    const auto& cls = Class::Handle(zone, toplevel_class());
    if (!cls.IsNull()) {
      cls.EnsureDeclarationLoaded();
    }
  }
  Object& value = Object::Handle(zone);
  {
    SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
    MetadataMap map(metadata());
    value = map.GetOrNull(declaration);
    set_metadata(map.Release());
  }
  if (value.IsNull()) {
    // There is no metadata for this object.
    return Object::empty_array().ptr();
  }
  if (!value.IsSmi()) {
    // Metadata is already evaluated.
    ASSERT(value.IsArray() || value.IsLanguageError());
    return value.ptr();
  }
  const auto& smi_value = Smi::Cast(value);
  intptr_t kernel_offset = smi_value.Value();
  ASSERT(kernel_offset > 0);
  const auto& evaluated_value = Object::Handle(
      zone, kernel::EvaluateMetadata(
                *this, kernel_offset,
                /* is_annotations_offset = */ declaration.IsLibrary() ||
                    declaration.IsNamespace()));
  if (evaluated_value.IsArray() || evaluated_value.IsNull() ||
      evaluated_value.IsLanguageError()) {
    ASSERT(evaluated_value.ptr() != Object::empty_array().ptr());
    SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
    MetadataMap map(metadata());
    if (map.GetOrNull(declaration) == smi_value.ptr()) {
      map.UpdateOrInsert(declaration, evaluated_value);
    } else {
      ASSERT(map.GetOrNull(declaration) == evaluated_value.ptr());
    }
    set_metadata(map.Release());
  }
  return evaluated_value.ptr();
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

#if !defined(DART_PRECOMPILED_RUNTIME)
static bool HasPragma(const Object& declaration) {
  return (declaration.IsClass() && Class::Cast(declaration).has_pragma()) ||
         (declaration.IsFunction() &&
          Function::Cast(declaration).has_pragma()) ||
         (declaration.IsField() && Field::Cast(declaration).has_pragma());
}

void Library::EvaluatePragmas() {
  Object& declaration = Object::Handle();
  const GrowableObjectArray& declarations =
      GrowableObjectArray::Handle(GrowableObjectArray::New());
  {
    auto thread = Thread::Current();
    SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
    MetadataMap map(metadata());
    MetadataMap::Iterator it(&map);
    while (it.MoveNext()) {
      const intptr_t entry = it.Current();
      ASSERT(entry != -1);
      declaration = map.GetKey(entry);
      if (HasPragma(declaration)) {
        declarations.Add(declaration);
      }
    }
    set_metadata(map.Release());
  }
  for (intptr_t i = 0; i < declarations.Length(); ++i) {
    declaration = declarations.At(i);
    GetMetadata(declaration);
  }
}

void Library::CopyPragmas(const Library& old_lib) {
  auto thread = Thread::Current();
  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
  MetadataMap new_map(metadata());
  MetadataMap old_map(old_lib.metadata());
  Object& declaration = Object::Handle();
  Object& value = Object::Handle();
  MetadataMap::Iterator it(&old_map);
  while (it.MoveNext()) {
    const intptr_t entry = it.Current();
    ASSERT(entry != -1);
    declaration = old_map.GetKey(entry);
    if (HasPragma(declaration)) {
      value = old_map.GetPayload(entry, 0);
      ASSERT(!value.IsNull());
      // Pragmas should be evaluated during hot reload phase 1
      // (when checkpointing libraries).
      ASSERT(!value.IsSmi());
      new_map.UpdateOrInsert(declaration, value);
    }
  }
  old_lib.set_metadata(old_map.Release());
  set_metadata(new_map.Release());
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

static bool ShouldBePrivate(const String& name) {
  return (name.Length() >= 1 && name.CharAt(0) == '_') ||
         (name.Length() >= 5 &&
          (name.CharAt(4) == '_' &&
           (name.CharAt(0) == 'g' || name.CharAt(0) == 's') &&
           name.CharAt(1) == 'e' && name.CharAt(2) == 't' &&
           name.CharAt(3) == ':'));
}

void Library::RehashDictionary(const Array& old_dict,
                               intptr_t new_dict_size) const {
  intptr_t old_dict_size = old_dict.Length() - 1;
  const Array& new_dict =
      Array::Handle(Array::New(new_dict_size + 1, Heap::kOld));
  // Rehash all elements from the original dictionary
  // to the newly allocated array.
  Object& entry = Class::Handle();
  String& entry_name = String::Handle();
  Object& new_entry = Object::Handle();
  intptr_t used = 0;
  for (intptr_t i = 0; i < old_dict_size; i++) {
    entry = old_dict.At(i);
    if (!entry.IsNull()) {
      entry_name = entry.DictionaryName();
      ASSERT(!entry_name.IsNull());
      const intptr_t hash = entry_name.Hash();
      intptr_t index = hash % new_dict_size;
      new_entry = new_dict.At(index);
      while (!new_entry.IsNull()) {
        index = (index + 1) % new_dict_size;  // Move to next element.
        new_entry = new_dict.At(index);
      }
      new_dict.SetAt(index, entry);
      used++;
    }
  }
  // Set used count.
  ASSERT(used < new_dict_size);  // Need at least one empty slot.
  new_entry = Smi::New(used);
  new_dict.SetAt(new_dict_size, new_entry);
  // Remember the new dictionary now.
  untag()->set_dictionary(new_dict.ptr());
}

void Library::AddObject(const Object& obj, const String& name) const {
  ASSERT(Thread::Current()->IsDartMutatorThread());
  ASSERT(obj.IsClass() || obj.IsFunction() || obj.IsField() ||
         obj.IsLibraryPrefix());
  ASSERT(name.Equals(String::Handle(obj.DictionaryName())));
  ASSERT(LookupLocalObject(name) == Object::null());
  const Array& dict = Array::Handle(dictionary());
  intptr_t dict_size = dict.Length() - 1;
  intptr_t index = name.Hash() % dict_size;

  Object& entry = Object::Handle();
  entry = dict.At(index);
  // An empty spot will be found because we keep the hash set at most 75% full.
  while (!entry.IsNull()) {
    index = (index + 1) % dict_size;
    entry = dict.At(index);
  }

  // Insert the object at the empty slot.
  dict.SetAt(index, obj);
  // One more element added.
  intptr_t used_elements = Smi::Value(Smi::RawCast(dict.At(dict_size))) + 1;
  const Smi& used = Smi::Handle(Smi::New(used_elements));
  dict.SetAt(dict_size, used);  // Update used count.

  // Rehash if symbol_table is 75% full.
  if (used_elements > ((dict_size / 4) * 3)) {
    // TODO(iposva): Avoid exponential growth.
    RehashDictionary(dict, 2 * dict_size);
  }

  // Invalidate the cache of loaded scripts.
  if (loaded_scripts() != Array::null()) {
    untag()->set_loaded_scripts(Array::null());
  }
}

// Lookup a name in the library's re-export namespace.
// This lookup can occur from two different threads: background compiler and
// mutator thread.
ObjectPtr Library::LookupReExport(const String& name,
                                  ZoneGrowableArray<intptr_t>* trail) const {
  if (!HasExports()) {
    return Object::null();
  }

  if (trail == nullptr) {
    trail = new ZoneGrowableArray<intptr_t>();
  }
  Object& obj = Object::Handle();

  const intptr_t lib_id = this->index();
  ASSERT(lib_id >= 0);  // We use -1 to indicate that a cycle was found.
  trail->Add(lib_id);
  const Array& exports = Array::Handle(this->exports());
  Namespace& ns = Namespace::Handle();
  for (int i = 0; i < exports.Length(); i++) {
    ns ^= exports.At(i);
    obj = ns.Lookup(name, trail);
    if (!obj.IsNull()) {
      // The Lookup call above may return a setter x= when we are looking
      // for the name x. Make sure we only return when a matching name
      // is found.
      String& obj_name = String::Handle(obj.DictionaryName());
      if (Field::IsSetterName(obj_name) == Field::IsSetterName(name)) {
        break;
      }
    }
  }
  trail->RemoveLast();
  return obj.ptr();
}

ObjectPtr Library::LookupEntry(const String& name, intptr_t* index) const {
  ASSERT(!IsNull());
  Thread* thread = Thread::Current();
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_OBJECT_HANDLESCOPE(thread);
  REUSABLE_STRING_HANDLESCOPE(thread);
  Array& dict = thread->ArrayHandle();
  dict = dictionary();
  intptr_t dict_size = dict.Length() - 1;
  *index = name.Hash() % dict_size;
  Object& entry = thread->ObjectHandle();
  String& entry_name = thread->StringHandle();
  entry = dict.At(*index);
  // Search the entry in the hash set.
  while (!entry.IsNull()) {
    entry_name = entry.DictionaryName();
    ASSERT(!entry_name.IsNull());
    if (entry_name.Equals(name)) {
      return entry.ptr();
    }
    *index = (*index + 1) % dict_size;
    entry = dict.At(*index);
  }
  return Object::null();
}

void Library::AddClass(const Class& cls) const {
  ASSERT(!Compiler::IsBackgroundCompilation());
  const String& class_name = String::Handle(cls.Name());
  AddObject(cls, class_name);
  // Link class to this library.
  cls.set_library(*this);
}

static void AddScriptIfUnique(const GrowableObjectArray& scripts,
                              const Script& candidate) {
  if (candidate.IsNull()) {
    return;
  }
  Script& script_obj = Script::Handle();

  for (int i = 0; i < scripts.Length(); i++) {
    script_obj ^= scripts.At(i);
    if (script_obj.ptr() == candidate.ptr()) {
      // We already have a reference to this script.
      return;
    }
  }
  // Add script to the list of scripts.
  scripts.Add(candidate);
}

ArrayPtr Library::LoadedScripts() const {
  // We compute the list of loaded scripts lazily. The result is
  // cached in loaded_scripts_.
  if (loaded_scripts() == Array::null()) {
    // TODO(jensj): This can be cleaned up.
    // It really should just return the content of `used_scripts`, and there
    // should be no need to do the O(n) call to `AddScriptIfUnique` per script.

    // Iterate over the library dictionary and collect all scripts.
    const GrowableObjectArray& scripts =
        GrowableObjectArray::Handle(GrowableObjectArray::New(8));
    Object& entry = Object::Handle();
    Class& cls = Class::Handle();
    Script& owner_script = Script::Handle();
    DictionaryIterator it(*this);
    while (it.HasNext()) {
      entry = it.GetNext();
      if (entry.IsClass()) {
        owner_script = Class::Cast(entry).script();
      } else if (entry.IsFunction()) {
        owner_script = Function::Cast(entry).script();
      } else if (entry.IsField()) {
        owner_script = Field::Cast(entry).Script();
      } else {
        continue;
      }
      AddScriptIfUnique(scripts, owner_script);
    }

    // Add all scripts from patch classes.
    GrowableObjectArray& patches = GrowableObjectArray::Handle(used_scripts());
    for (intptr_t i = 0; i < patches.Length(); i++) {
      entry = patches.At(i);
      if (entry.IsClass()) {
        owner_script = Class::Cast(entry).script();
      } else {
        ASSERT(entry.IsScript());
        owner_script = Script::Cast(entry).ptr();
      }
      AddScriptIfUnique(scripts, owner_script);
    }

    cls = toplevel_class();
    if (!cls.IsNull()) {
      owner_script = cls.script();
      AddScriptIfUnique(scripts, owner_script);
      // Special case: Scripts that only contain external top-level functions
      // are not included above, but can be referenced through a library's
      // anonymous classes. Example: dart-core:identical.dart.
      Function& func = Function::Handle();
      Array& functions = Array::Handle(cls.current_functions());
      for (intptr_t j = 0; j < functions.Length(); j++) {
        func ^= functions.At(j);
        if (func.is_external()) {
          owner_script = func.script();
          AddScriptIfUnique(scripts, owner_script);
        }
      }
    }

    // Create the array of scripts and cache it in loaded_scripts_.
    const Array& scripts_array = Array::Handle(Array::MakeFixedLength(scripts));
    untag()->set_loaded_scripts(scripts_array.ptr());
  }
  return loaded_scripts();
}

// TODO(hausner): we might want to add a script dictionary to the
// library class to make this lookup faster.
ScriptPtr Library::LookupScript(const String& url,
                                bool useResolvedUri /* = false */) const {
  const intptr_t url_length = url.Length();
  if (url_length == 0) {
    return Script::null();
  }
  const Array& scripts = Array::Handle(LoadedScripts());
  Script& script = Script::Handle();
  String& script_url = String::Handle();
  const intptr_t num_scripts = scripts.Length();
  for (int i = 0; i < num_scripts; i++) {
    script ^= scripts.At(i);
    if (useResolvedUri) {
      // Use for urls with 'org-dartlang-sdk:' or 'file:' schemes
      script_url = script.resolved_url();
    } else {
      // Use for urls with 'dart:', 'package:', or 'file:' schemes
      script_url = script.url();
    }
    const intptr_t start_idx = script_url.Length() - url_length;
    if ((start_idx == 0) && url.Equals(script_url)) {
      return script.ptr();
    } else if (start_idx > 0) {
      // If we do a suffix match, only match if the partial path
      // starts at or immediately after the path separator.
      if (((url.CharAt(0) == '/') ||
           (script_url.CharAt(start_idx - 1) == '/')) &&
          url.Equals(script_url, start_idx, url_length)) {
        return script.ptr();
      }
    }
  }
  return Script::null();
}

void Library::EnsureTopLevelClassIsFinalized() const {
  if (toplevel_class() == Object::null()) {
    return;
  }
  Thread* thread = Thread::Current();
  const Class& cls = Class::Handle(thread->zone(), toplevel_class());
  if (cls.is_finalized()) {
    return;
  }
  const Error& error =
      Error::Handle(thread->zone(), cls.EnsureIsFinalized(thread));
  if (!error.IsNull()) {
    Exceptions::PropagateError(error);
  }
}

ObjectPtr Library::LookupLocalObject(const String& name) const {
  intptr_t index;
  return LookupEntry(name, &index);
}

ObjectPtr Library::LookupLocalOrReExportObject(const String& name) const {
  intptr_t index;
  EnsureTopLevelClassIsFinalized();
  const Object& result = Object::Handle(LookupEntry(name, &index));
  if (!result.IsNull() && !result.IsLibraryPrefix()) {
    return result.ptr();
  }
  return LookupReExport(name);
}

FieldPtr Library::LookupFieldAllowPrivate(const String& name) const {
  EnsureTopLevelClassIsFinalized();
  Object& obj = Object::Handle(LookupLocalObjectAllowPrivate(name));
  if (obj.IsField()) {
    return Field::Cast(obj).ptr();
  }
  return Field::null();
}

FunctionPtr Library::LookupFunctionAllowPrivate(const String& name) const {
  EnsureTopLevelClassIsFinalized();
  Object& obj = Object::Handle(LookupLocalObjectAllowPrivate(name));
  if (obj.IsFunction()) {
    return Function::Cast(obj).ptr();
  }
  return Function::null();
}

ObjectPtr Library::LookupLocalObjectAllowPrivate(const String& name) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Object& obj = Object::Handle(zone, Object::null());
  obj = LookupLocalObject(name);
  if (obj.IsNull() && ShouldBePrivate(name)) {
    String& private_name = String::Handle(zone, PrivateName(name));
    obj = LookupLocalObject(private_name);
  }
  return obj.ptr();
}

ClassPtr Library::LookupClass(const String& name) const {
  Object& obj = Object::Handle(LookupLocalObject(name));
  if (obj.IsClass()) {
    return Class::Cast(obj).ptr();
  }
  return Class::null();
}

ClassPtr Library::LookupClassAllowPrivate(const String& name) const {
  Object& obj = Object::Handle(LookupLocalObjectAllowPrivate(name));
  if (obj.IsClass()) {
    return Class::Cast(obj).ptr();
  }
  return Class::null();
}

LibraryPrefixPtr Library::LookupLocalLibraryPrefix(const String& name) const {
  const Object& obj = Object::Handle(LookupLocalObject(name));
  if (obj.IsLibraryPrefix()) {
    return LibraryPrefix::Cast(obj).ptr();
  }
  return LibraryPrefix::null();
}

void Library::set_toplevel_class(const Class& value) const {
  ASSERT(untag()->toplevel_class() == Class::null());
  untag()->set_toplevel_class(value.ptr());
}

void Library::set_dependencies(const Array& deps) const {
  untag()->set_dependencies(deps.ptr());
}

void Library::set_metadata(const Array& value) const {
  if (untag()->metadata() != value.ptr()) {
    DEBUG_ASSERT(
        IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
    untag()->set_metadata(value.ptr());
  }
}

LibraryPtr Library::ImportLibraryAt(intptr_t index) const {
  Namespace& import = Namespace::Handle(ImportAt(index));
  if (import.IsNull()) {
    return Library::null();
  }
  return import.target();
}

NamespacePtr Library::ImportAt(intptr_t index) const {
  if ((index < 0) || index >= num_imports()) {
    return Namespace::null();
  }
  const Array& import_list = Array::Handle(imports());
  return Namespace::RawCast(import_list.At(index));
}

void Library::DropDependenciesAndCaches() const {
  untag()->set_imports(Object::empty_array().ptr());
  untag()->set_exports(Object::empty_array().ptr());
  StoreNonPointer(&untag()->num_imports_, 0);
  untag()->set_loaded_scripts(Array::null());
  untag()->set_dependencies(Array::null());
#if defined(PRODUCT)
  // used_scripts is only used by vm-service.
  untag()->set_used_scripts(GrowableObjectArray::null());
#endif
}

void Library::AddImport(const Namespace& ns) const {
  Array& imports = Array::Handle(this->imports());
  intptr_t capacity = imports.Length();
  if (num_imports() == capacity) {
    capacity = capacity + kImportsCapacityIncrement + (capacity >> 2);
    imports = Array::Grow(imports, capacity);
    untag()->set_imports(imports.ptr());
  }
  intptr_t index = num_imports();
  imports.SetAt(index, ns);
  set_num_imports(index + 1);
}

// Convenience function to determine whether the export list is
// non-empty.
bool Library::HasExports() const {
  return exports() != Object::empty_array().ptr();
}

// We add one namespace at a time to the exports array and don't
// pre-allocate any unused capacity. The assumption is that
// re-exports are quite rare.
void Library::AddExport(const Namespace& ns) const {
  Array& exports = Array::Handle(this->exports());
  intptr_t num_exports = exports.Length();
  exports = Array::Grow(exports, num_exports + 1);
  untag()->set_exports(exports.ptr());
  exports.SetAt(num_exports, ns);
}

static ArrayPtr NewDictionary(intptr_t initial_size) {
  const Array& dict = Array::Handle(Array::New(initial_size + 1, Heap::kOld));
  // The last element of the dictionary specifies the number of in use slots.
  dict.SetAt(initial_size, Object::smi_zero());
  return dict.ptr();
}

void Library::InitClassDictionary() const {
  Thread* thread = Thread::Current();
  ASSERT(thread->IsDartMutatorThread());
  REUSABLE_FUNCTION_HANDLESCOPE(thread);
  Array& dictionary = thread->ArrayHandle();
  // TODO(iposva): Find reasonable initial size.
  const int kInitialElementCount = 16;
  dictionary = NewDictionary(kInitialElementCount);
  untag()->set_dictionary(dictionary.ptr());
}

void Library::InitImportList() const {
  const Array& imports =
      Array::Handle(Array::New(kInitialImportsCapacity, Heap::kOld));
  untag()->set_imports(imports.ptr());
  StoreNonPointer(&untag()->num_imports_, 0);
}

LibraryPtr Library::New() {
  ASSERT(Object::library_class() != Class::null());
  return Object::Allocate<Library>(Heap::kOld);
}

LibraryPtr Library::NewLibraryHelper(const String& url, bool import_core_lib) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  ASSERT(thread->IsDartMutatorThread());
  // Force the url to have a hash code.
  url.Hash();
  const bool dart_scheme = url.StartsWith(Symbols::DartScheme());
  const Library& result = Library::Handle(zone, Library::New());
  result.untag()->set_name(Symbols::Empty().ptr());
  result.untag()->set_url(url.ptr());
  result.untag()->set_dictionary(Object::empty_array().ptr());
  Array& array = Array::Handle(zone);
  array = HashTables::New<MetadataMap>(4, Heap::kOld);
  result.untag()->set_metadata(array.ptr());
  result.untag()->set_toplevel_class(Class::null());
  GrowableObjectArray& list = GrowableObjectArray::Handle(zone);
  list = GrowableObjectArray::New(Object::empty_array(), Heap::kOld);
  result.untag()->set_used_scripts(list.ptr());
  result.untag()->set_imports(Object::empty_array().ptr());
  result.untag()->set_exports(Object::empty_array().ptr());
  NOT_IN_PRECOMPILED_RUNTIME(
      result.untag()->set_kernel_program_info(KernelProgramInfo::null()));
  result.untag()->set_loaded_scripts(Array::null());
  result.set_native_entry_resolver(nullptr);
  result.set_native_entry_symbol_resolver(nullptr);
  result.set_ffi_native_resolver(nullptr);
  result.set_flags(0);
  result.set_is_in_fullsnapshot(false);
  // This logic is also in the DAP debug adapter in DDS to avoid needing
  // to call setLibraryDebuggable for every library for every isolate.
  // If these defaults change, the same should be done there in
  // dap/IsolateManager._getIsLibraryDebuggableByDefault.
  if (dart_scheme) {
    // Only debug dart: libraries if we have been requested to show invisible
    // frames.
    result.set_debuggable(FLAG_show_invisible_frames);
  } else {
    // Default to debuggable for all other libraries.
    result.set_debuggable(true);
  }
  result.set_is_dart_scheme(dart_scheme);
  NOT_IN_PRECOMPILED(
      result.StoreNonPointer(&result.untag()->kernel_library_index_, -1));
  result.StoreNonPointer(&result.untag()->load_state_,
                         UntaggedLibrary::kAllocated);
  result.StoreNonPointer(&result.untag()->index_, -1);
  result.InitClassDictionary();
  result.InitImportList();
  result.AllocatePrivateKey();
  if (import_core_lib) {
    const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
    ASSERT(!core_lib.IsNull());
    const Namespace& ns =
        Namespace::Handle(zone, Namespace::New(core_lib, Object::null_array(),
                                               Object::null_array(), result));
    result.AddImport(ns);
  }
  return result.ptr();
}

LibraryPtr Library::New(const String& url) {
  return NewLibraryHelper(url, false);
}

void Library::set_flags(uint8_t flags) const {
  StoreNonPointer(&untag()->flags_, flags);
}

void Library::InitCoreLibrary(IsolateGroup* isolate_group) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const String& core_lib_url = Symbols::DartCore();
  const Library& core_lib =
      Library::Handle(zone, Library::NewLibraryHelper(core_lib_url, false));
  core_lib.SetLoadRequested();
  core_lib.Register(thread);
  isolate_group->object_store()->set_bootstrap_library(ObjectStore::kCore,
                                                       core_lib);
  isolate_group->object_store()->set_root_library(Library::Handle());
}

// Invoke the function, or noSuchMethod if it is null.
static ObjectPtr InvokeInstanceFunction(
    Thread* thread,
    const Instance& receiver,
    const Function& function,
    const String& target_name,
    const Array& args,
    const Array& args_descriptor_array,
    bool check_is_entrypoint,
    EntryPointPragma pragma,
    bool respect_reflectable,
    const TypeArguments& instantiator_type_args) {
  // Note "args" is already the internal arguments with the receiver as the
  // first element.
  ArgumentsDescriptor args_descriptor(args_descriptor_array);
  if (function.IsNull() ||
      !function.AreValidArguments(args_descriptor, nullptr) ||
      (respect_reflectable && !function.is_reflectable())) {
    return DartEntry::InvokeNoSuchMethod(thread, receiver, target_name, args,
                                         args_descriptor_array);
  }
  ObjectPtr type_error = function.DoArgumentTypesMatch(args, args_descriptor,
                                                       instantiator_type_args);
  if (type_error != Error::null()) {
    return type_error;
  }
  if (check_is_entrypoint) {
    CHECK_ERROR(function.VerifyEntryPoint(pragma));
  }
  return DartEntry::InvokeFunction(function, args, args_descriptor_array);
}

static bool IsLookupOfMainFunctionInRootLibrary(const Library& lib,
                                                const String& name) {
  return name.Equals(Symbols::main()) &&
         lib.ptr() == IsolateGroup::Current()->object_store()->root_library();
}

ObjectPtr Library::InvokeGetter(const String& getter_name,
                                bool check_is_entrypoint,
                                bool respect_reflectable,
                                bool for_invocation) const {
  Object& obj = Object::Handle(LookupLocalOrReExportObject(getter_name));
  Function& getter = Function::Handle();
  if (obj.IsField()) {
    const Field& field = Field::Cast(obj);
    if (!field.IsUninitialized()) {
      if (check_is_entrypoint) {
        CHECK_ERROR(field.VerifyEntryPoint(EntryPointPragma::kGetterOnly));
      }
      return field.StaticValue();
    }
    // An uninitialized field was found.  Check for a getter in the field's
    // owner class.
    const Class& klass = Class::Handle(field.Owner());
    const String& internal_getter_name =
        String::Handle(Field::GetterName(getter_name));
    getter = klass.LookupStaticFunction(internal_getter_name);
  } else {
    // No field found. Check for a getter in the lib.
    const String& internal_getter_name =
        String::Handle(Field::GetterName(getter_name));
    obj = LookupLocalOrReExportObject(internal_getter_name);
    if (obj.IsFunction()) {
      getter = Function::Cast(obj).ptr();
    } else if (!for_invocation) {
      // No need to re-lookup the getter name if coming from Invoke(), since
      // it already failed there.
      obj = LookupLocalOrReExportObject(getter_name);
      if (obj.IsFunction()) {
        const auto& function = Function::Cast(obj);
        if (function.SafeToClosurize()) {
          // The main function of the root library always has a retained
          // implicit static closure.
          if (check_is_entrypoint &&
              !IsLookupOfMainFunctionInRootLibrary(*this, getter_name)) {
            CHECK_ERROR(
                function.VerifyEntryPoint(EntryPointPragma::kGetterOnly));
          }
          // Looking for a getter but found a regular method: closurize it.
          const auto& closure_function =
              Function::Handle(function.ImplicitClosureFunction());
          return closure_function.ImplicitStaticClosure();
        }
      }
    }
  }

  if (getter.IsNull() || (respect_reflectable && !getter.is_reflectable())) {
    if (for_invocation) {
      // Instead of throwing an NSM, indicate that no getter was found by
      // returning a value that cannot be returned by a getter (here,
      // the sentinel value).
      return Object::sentinel().ptr();
    }
    return ThrowNoSuchMethod(Object::null_string(), getter_name,
                             Object::null_array(), Object::null_array(),
                             InvocationMirror::kTopLevel,
                             InvocationMirror::kGetter);
  }

  if (check_is_entrypoint) {
    CHECK_ERROR(getter.VerifyEntryPoint(EntryPointPragma::kGetterOnly));
  }
  // Invoke the getter and return the result.
  return DartEntry::InvokeFunction(getter, Object::empty_array());
}

ObjectPtr Library::InvokeSetter(const String& setter_name,
                                const Instance& value,
                                bool check_is_entrypoint,
                                bool respect_reflectable) const {
  Object& obj = Object::Handle(LookupLocalOrReExportObject(setter_name));
  const String& internal_setter_name =
      String::Handle(Field::SetterName(setter_name));
  AbstractType& setter_type = AbstractType::Handle();
  AbstractType& argument_type = AbstractType::Handle(value.GetType(Heap::kOld));
  if (obj.IsField()) {
    const Field& field = Field::Cast(obj);
    setter_type = field.type();
    if (!argument_type.IsNullType() && !setter_type.IsDynamicType() &&
        !value.IsInstanceOf(setter_type, Object::null_type_arguments(),
                            Object::null_type_arguments())) {
      return ThrowTypeError(field.token_pos(), value, setter_type, setter_name);
    }
    if (field.is_final() || (respect_reflectable && !field.is_reflectable())) {
      const int kNumArgs = 1;
      const Array& args = Array::Handle(Array::New(kNumArgs));
      args.SetAt(0, value);

      return ThrowNoSuchMethod(Object::null_string(), internal_setter_name,
                               args, Object::null_array(),
                               InvocationMirror::kTopLevel,
                               InvocationMirror::kSetter);
    }
    if (check_is_entrypoint) {
      CHECK_ERROR(field.VerifyEntryPoint(EntryPointPragma::kSetterOnly));
    }
    field.SetStaticValue(value);
    return value.ptr();
  }

  Function& setter = Function::Handle();
  obj = LookupLocalOrReExportObject(internal_setter_name);
  if (obj.IsFunction()) {
    setter ^= obj.ptr();
  }

  const int kNumArgs = 1;
  const Array& args = Array::Handle(Array::New(kNumArgs));
  args.SetAt(0, value);
  if (setter.IsNull() || (respect_reflectable && !setter.is_reflectable())) {
    return ThrowNoSuchMethod(Object::null_string(), internal_setter_name, args,
                             Object::null_array(), InvocationMirror::kTopLevel,
                             InvocationMirror::kSetter);
  }

  setter_type = setter.ParameterTypeAt(0);
  if (!argument_type.IsNullType() && !setter_type.IsDynamicType() &&
      !value.IsInstanceOf(setter_type, Object::null_type_arguments(),
                          Object::null_type_arguments())) {
    return ThrowTypeError(setter.token_pos(), value, setter_type, setter_name);
  }

  if (check_is_entrypoint) {
    CHECK_ERROR(setter.VerifyEntryPoint(EntryPointPragma::kSetterOnly));
  }
  return DartEntry::InvokeFunction(setter, args);
}

ObjectPtr Library::Invoke(const String& function_name,
                          const Array& args,
                          const Array& arg_names,
                          bool check_is_entrypoint,
                          bool respect_reflectable) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  // We don't pass any explicit type arguments, which will be understood as
  // using dynamic for any function type arguments by lower layers.
  const int kTypeArgsLen = 0;
  const Array& args_descriptor_array = Array::Handle(
      zone, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length(),
                                          arg_names, Heap::kNew));
  ArgumentsDescriptor args_descriptor(args_descriptor_array);

  auto& function = Function::Handle(zone);
  auto& result =
      Object::Handle(zone, LookupLocalOrReExportObject(function_name));
  if (result.IsFunction()) {
    function ^= result.ptr();
  }

  if (function.IsNull()) {
    // Didn't find a method: try to find a getter and invoke call on its result.
    const Object& getter_result =
        Object::Handle(zone, InvokeGetter(function_name, check_is_entrypoint,
                                          respect_reflectable,
                                          /*for_invocation=*/true));
    if (getter_result.IsError()) {
      return getter_result.ptr();
    } else if (getter_result.ptr() != Object::sentinel().ptr()) {
      const auto& call_args_descriptor_array = Array::Handle(
          zone, ArgumentsDescriptor::NewBoxed(args_descriptor.TypeArgsLen(),
                                              args_descriptor.Count() + 1,
                                              arg_names, Heap::kNew));
      const auto& call_args = Array::Handle(
          zone,
          CreateCallableArgumentsFromStatic(zone, Instance::Cast(getter_result),
                                            args, arg_names, args_descriptor));
      return DartEntry::InvokeClosure(thread, call_args,
                                      call_args_descriptor_array);
    }
  }

  if (function.IsNull() ||
      (respect_reflectable && !function.is_reflectable())) {
    return ThrowNoSuchMethod(Object::null_string(), function_name, args,
                             arg_names, InvocationMirror::kTopLevel,
                             InvocationMirror::kMethod);
  }
  if (!function.AreValidArguments(args_descriptor, nullptr)) {
    return ThrowNoSuchMethod(
        String::Handle(function.UserVisibleSignature()), function_name, args,
        arg_names, InvocationMirror::kTopLevel, InvocationMirror::kMethod);
  }
  // This is a static function, so we pass an empty instantiator tav.
  ASSERT(function.is_static());
  ObjectPtr type_error = function.DoArgumentTypesMatch(
      args, args_descriptor, Object::empty_type_arguments());
  if (type_error != Error::null()) {
    return type_error;
  }
  // The main function of the root library is always callable.
  if (check_is_entrypoint &&
      !IsLookupOfMainFunctionInRootLibrary(*this, function_name)) {
    CHECK_ERROR(function.VerifyEntryPoint(EntryPointPragma::kCallOnly));
  }
  return DartEntry::InvokeFunction(function, args, args_descriptor_array);
}

void Library::InitNativeWrappersLibrary(IsolateGroup* isolate_group,
                                        bool is_kernel) {
  const int kNumNativeWrappersClasses = 4;
  COMPILE_ASSERT((kNumNativeWrappersClasses > 0) &&
                 (kNumNativeWrappersClasses < 10));
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const String& native_flds_lib_url = Symbols::DartNativeWrappers();
  const Library& native_flds_lib = Library::Handle(
      zone, Library::NewLibraryHelper(native_flds_lib_url, false));
  const String& native_flds_lib_name = Symbols::DartNativeWrappersLibName();
  native_flds_lib.SetName(native_flds_lib_name);
  native_flds_lib.SetLoadRequested();
  native_flds_lib.Register(thread);
  native_flds_lib.SetLoadInProgress();
  isolate_group->object_store()->set_native_wrappers_library(native_flds_lib);
  const char* const kNativeWrappersClass = "NativeFieldWrapperClass";
  const int kNameLength = 25;
  ASSERT(kNameLength == (strlen(kNativeWrappersClass) + 1 + 1));
  char name_buffer[kNameLength];
  String& cls_name = String::Handle(zone);
  for (int fld_cnt = 1; fld_cnt <= kNumNativeWrappersClasses; fld_cnt++) {
    Utils::SNPrint(name_buffer, kNameLength, "%s%d", kNativeWrappersClass,
                   fld_cnt);
    cls_name = Symbols::New(thread, name_buffer);
    Class::NewNativeWrapper(native_flds_lib, cls_name, fld_cnt);
  }
  // NOTE: If we bootstrap from a Kernel IR file we want to generate the
  // synthetic constructors for the native wrapper classes.  We leave this up to
  // the [KernelLoader] who will take care of it later.
  if (!is_kernel) {
    native_flds_lib.SetLoaded();
  }
}

// LibraryLookupSet maps URIs to libraries.
class LibraryLookupTraits {
 public:
  static const char* Name() { return "LibraryLookupTraits"; }
  static bool ReportStats() { return false; }

  static bool IsMatch(const Object& a, const Object& b) {
    const String& a_str = String::Cast(a);
    const String& b_str = String::Cast(b);

    ASSERT(a_str.HasHash() && b_str.HasHash());
    return a_str.Equals(b_str);
  }

  static uword Hash(const Object& key) { return String::Cast(key).Hash(); }

  static ObjectPtr NewKey(const String& str) { return str.ptr(); }
};
typedef UnorderedHashMap<LibraryLookupTraits> LibraryLookupMap;

// Returns library with given url in current isolate, or nullptr.
LibraryPtr Library::LookupLibrary(Thread* thread, const String& url) {
  Zone* zone = thread->zone();
  ObjectStore* object_store = thread->isolate_group()->object_store();

  // Make sure the URL string has an associated hash code
  // to speed up the repeated equality checks.
  url.Hash();

  // Use the libraries map to lookup the library by URL.
  Library& lib = Library::Handle(zone);
  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
  if (object_store->libraries_map() == Array::null()) {
    return Library::null();
  } else {
    LibraryLookupMap map(object_store->libraries_map());
    lib ^= map.GetOrNull(url);
    ASSERT(map.Release().ptr() == object_store->libraries_map());
  }
  return lib.ptr();
}

bool Library::IsPrivate(const String& name) {
  if (ShouldBePrivate(name)) return true;
  // Factory names: List._fromLiteral.
  for (intptr_t i = 1; i < name.Length() - 1; i++) {
    if (name.CharAt(i) == '.') {
      if (name.CharAt(i + 1) == '_') {
        return true;
      }
    }
  }
  return false;
}

// Create a private key for this library. It is based on the hash of the
// library URI and the sequence number of the library to guarantee unique
// private keys without having to verify.
void Library::AllocatePrivateKey() const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  auto isolate_group = thread->isolate_group();

#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
  if (isolate_group->IsReloading()) {
    // When reloading, we need to make sure we use the original private key
    // if this library previously existed.
    ProgramReloadContext* program_reload_context =
        isolate_group->program_reload_context();
    const String& original_key =
        String::Handle(program_reload_context->FindLibraryPrivateKey(*this));
    if (!original_key.IsNull()) {
      untag()->set_private_key(original_key.ptr());
      return;
    }
  }
#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

  // Format of the private key is: "@<sequence number><6 digits of hash>
  const intptr_t hash_mask = 0x7FFFF;

  const String& url = String::Handle(zone, this->url());
  intptr_t hash_value = url.Hash() & hash_mask;

  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
      zone, isolate_group->object_store()->libraries());
  intptr_t sequence_value = libs.Length();

  char private_key[32];
  Utils::SNPrint(private_key, sizeof(private_key), "%c%" Pd "%06" Pd "",
                 kPrivateKeySeparator, sequence_value, hash_value);
  const String& key =
      String::Handle(zone, String::New(private_key, Heap::kOld));
  key.Hash();  // This string may end up in the VM isolate.
  untag()->set_private_key(key.ptr());
}

const String& Library::PrivateCoreLibName(const String& member) {
  const Library& core_lib = Library::Handle(Library::CoreLibrary());
  const String& private_name = String::ZoneHandle(core_lib.PrivateName(member));
  return private_name;
}

bool Library::IsPrivateCoreLibName(const String& name, const String& member) {
  Zone* zone = Thread::Current()->zone();
  const auto& core_lib = Library::Handle(zone, Library::CoreLibrary());
  const auto& private_key = String::Handle(zone, core_lib.private_key());

  ASSERT(core_lib.IsPrivate(member));
  return name.EqualsConcat(member, private_key);
}

ClassPtr Library::LookupCoreClass(const String& class_name) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
  String& name = String::Handle(zone, class_name.ptr());
  if (class_name.CharAt(0) == kPrivateIdentifierStart) {
    // Private identifiers are mangled on a per library basis.
    name = Symbols::FromConcat(thread, name,
                               String::Handle(zone, core_lib.private_key()));
  }
  return core_lib.LookupClass(name);
}

// Cannot handle qualified names properly as it only appends private key to
// the end (e.g. _Alfa.foo -> _Alfa.foo@...).
StringPtr Library::PrivateName(const String& name) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  ASSERT(IsPrivate(name));
  // ASSERT(strchr(name, '@') == nullptr);
  String& str = String::Handle(zone);
  str = name.ptr();
  str = Symbols::FromConcat(thread, str,
                            String::Handle(zone, this->private_key()));
  return str.ptr();
}

LibraryPtr Library::GetLibrary(intptr_t index) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  auto isolate_group = thread->isolate_group();
  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
      zone, isolate_group->object_store()->libraries());
  ASSERT(!libs.IsNull());
  if ((0 <= index) && (index < libs.Length())) {
    Library& lib = Library::Handle(zone);
    lib ^= libs.At(index);
    return lib.ptr();
  }
  return Library::null();
}

void Library::Register(Thread* thread) const {
  Zone* zone = thread->zone();
  auto isolate_group = thread->isolate_group();
  ObjectStore* object_store = isolate_group->object_store();

  // A library is "registered" in two places:
  // - A growable array mapping from index to library.
  const String& lib_url = String::Handle(zone, url());
  ASSERT(Library::LookupLibrary(thread, lib_url) == Library::null());
  ASSERT(lib_url.HasHash());
  SafepointWriteRwLocker ml(thread, isolate_group->program_lock());
  GrowableObjectArray& libs =
      GrowableObjectArray::Handle(zone, object_store->libraries());
  ASSERT(!libs.IsNull());
  set_index(libs.Length());
  libs.Add(*this);

  // - A map from URL string to library.
  if (object_store->libraries_map() == Array::null()) {
    LibraryLookupMap map(HashTables::New<LibraryLookupMap>(16, Heap::kOld));
    object_store->set_libraries_map(map.Release());
  }

  LibraryLookupMap map(object_store->libraries_map());
  bool present = map.UpdateOrInsert(lib_url, *this);
  ASSERT(!present);
  object_store->set_libraries_map(map.Release());
}

void Library::RegisterLibraries(Thread* thread,
                                const GrowableObjectArray& libs) {
  Zone* zone = thread->zone();
  auto isolate_group = thread->isolate_group();
  Library& lib = Library::Handle(zone);
  String& lib_url = String::Handle(zone);

  LibraryLookupMap map(HashTables::New<LibraryLookupMap>(16, Heap::kOld));

  intptr_t len = libs.Length();
  for (intptr_t i = 0; i < len; i++) {
    lib ^= libs.At(i);
    lib_url = lib.url();
    map.InsertNewOrGetValue(lib_url, lib);
  }
  // Now remember these in the isolate's object store.
  isolate_group->object_store()->set_libraries(libs);
  isolate_group->object_store()->set_libraries_map(map.Release());
}

LibraryPtr Library::AsyncLibrary() {
  return IsolateGroup::Current()->object_store()->async_library();
}

LibraryPtr Library::ConcurrentLibrary() {
  return IsolateGroup::Current()->object_store()->concurrent_library();
}

LibraryPtr Library::ConvertLibrary() {
  return IsolateGroup::Current()->object_store()->convert_library();
}

LibraryPtr Library::CoreLibrary() {
  return IsolateGroup::Current()->object_store()->core_library();
}

LibraryPtr Library::CollectionLibrary() {
  return IsolateGroup::Current()->object_store()->collection_library();
}

LibraryPtr Library::CompactHashLibrary() {
  return IsolateGroup::Current()->object_store()->_compact_hash_library();
}

LibraryPtr Library::DeveloperLibrary() {
  return IsolateGroup::Current()->object_store()->developer_library();
}

LibraryPtr Library::FfiLibrary() {
  return IsolateGroup::Current()->object_store()->ffi_library();
}

LibraryPtr Library::InternalLibrary() {
  return IsolateGroup::Current()->object_store()->_internal_library();
}

LibraryPtr Library::IsolateLibrary() {
  return IsolateGroup::Current()->object_store()->isolate_library();
}

LibraryPtr Library::MathLibrary() {
  return IsolateGroup::Current()->object_store()->math_library();
}

#if !defined(DART_PRECOMPILED_RUNTIME)
LibraryPtr Library::MirrorsLibrary() {
  return IsolateGroup::Current()->object_store()->mirrors_library();
}
#endif

LibraryPtr Library::NativeWrappersLibrary() {
  return IsolateGroup::Current()->object_store()->native_wrappers_library();
}

LibraryPtr Library::TypedDataLibrary() {
  return IsolateGroup::Current()->object_store()->typed_data_library();
}

LibraryPtr Library::VMServiceLibrary() {
  return IsolateGroup::Current()->object_store()->_vmservice_library();
}

const char* Library::ToCString() const {
  NoSafepointScope no_safepoint;
  const String& name = String::Handle(url());
  return OS::SCreate(Thread::Current()->zone(), "Library:'%s'",
                     name.ToCString());
}

LibraryPtr LibraryPrefix::GetLibrary(int index) const {
  if ((index >= 0) || (index < num_imports())) {
    const Array& imports = Array::Handle(this->imports());
    Namespace& import = Namespace::Handle();
    import ^= imports.At(index);
    return import.target();
  }
  return Library::null();
}

void LibraryPrefix::AddImport(const Namespace& import) const {
  intptr_t num_current_imports = num_imports();

  // Prefixes with deferred libraries can only contain one library.
  ASSERT((num_current_imports == 0) || !is_deferred_load());

  // The library needs to be added to the list.
  Array& imports = Array::Handle(this->imports());
  const intptr_t length = (imports.IsNull()) ? 0 : imports.Length();
  // Grow the list if it is full.
  if (num_current_imports >= length) {
    const intptr_t new_length = length + kIncrementSize + (length >> 2);
    imports = Array::Grow(imports, new_length, Heap::kOld);
    set_imports(imports);
  }
  imports.SetAt(num_current_imports, import);
  set_num_imports(num_current_imports + 1);
}

LibraryPrefixPtr LibraryPrefix::New() {
  return Object::Allocate<LibraryPrefix>(Heap::kOld);
}

LibraryPrefixPtr LibraryPrefix::New(const String& name,
                                    const Namespace& import,
                                    bool deferred_load,
                                    const Library& importer) {
  const LibraryPrefix& result = LibraryPrefix::Handle(LibraryPrefix::New());
  result.set_name(name);
  result.set_num_imports(0);
  result.set_importer(importer);
  result.StoreNonPointer(&result.untag()->is_deferred_load_, deferred_load);
  result.set_imports(Array::Handle(Array::New(kInitialSize)));
  result.AddImport(import);
  return result.ptr();
}

void LibraryPrefix::set_name(const String& value) const {
  ASSERT(value.IsSymbol());
  untag()->set_name(value.ptr());
}

void LibraryPrefix::set_imports(const Array& value) const {
  untag()->set_imports(value.ptr());
}

void LibraryPrefix::set_num_imports(intptr_t value) const {
  if (!Utils::IsUint(16, value)) {
    ReportTooManyImports(Library::Handle(importer()));
  }
  StoreNonPointer(&untag()->num_imports_, value);
}

void LibraryPrefix::set_importer(const Library& value) const {
  untag()->set_importer(value.ptr());
}

const char* LibraryPrefix::ToCString() const {
  const String& prefix = String::Handle(name());
  return prefix.ToCString();
}

const char* Namespace::ToCString() const {
  const Library& lib = Library::Handle(target());
  return OS::SCreate(Thread::Current()->zone(), "Namespace for library '%s'",
                     lib.ToCString());
}

bool Namespace::HidesName(const String& name) const {
  // Quick check for common case with no combinators.
  if (hide_names() == show_names()) {
    ASSERT(hide_names() == Array::null());
    return false;
  }
  const String* plain_name = &name;
  if (Field::IsGetterName(name)) {
    plain_name = &String::Handle(Field::NameFromGetter(name));
  } else if (Field::IsSetterName(name)) {
    plain_name = &String::Handle(Field::NameFromSetter(name));
  }
  // Check whether the name is in the list of explicitly hidden names.
  if (hide_names() != Array::null()) {
    const Array& names = Array::Handle(hide_names());
    String& hidden = String::Handle();
    intptr_t num_names = names.Length();
    for (intptr_t i = 0; i < num_names; i++) {
      hidden ^= names.At(i);
      if (plain_name->Equals(hidden)) {
        return true;
      }
    }
  }
  // The name is not explicitly hidden. Now check whether it is in the
  // list of explicitly visible names, if there is one.
  if (show_names() != Array::null()) {
    const Array& names = Array::Handle(show_names());
    String& shown = String::Handle();
    intptr_t num_names = names.Length();
    for (intptr_t i = 0; i < num_names; i++) {
      shown ^= names.At(i);
      if (plain_name->Equals(shown)) {
        return false;
      }
    }
    // There is a list of visible names. The name we're looking for is not
    // contained in the list, so it is hidden.
    return true;
  }
  // The name is not filtered out.
  return false;
}

// Look up object with given name in library and filter out hidden
// names. Also look up getters and setters.
ObjectPtr Namespace::Lookup(const String& name,
                            ZoneGrowableArray<intptr_t>* trail) const {
  Zone* zone = Thread::Current()->zone();
  const Library& lib = Library::Handle(zone, target());

  if (trail != nullptr) {
    // Look for cycle in reexport graph.
    for (int i = 0; i < trail->length(); i++) {
      if (trail->At(i) == lib.index()) {
        for (int j = i + 1; j < trail->length(); j++) {
          (*trail)[j] = -1;
        }
        return Object::null();
      }
    }
  }

  lib.EnsureTopLevelClassIsFinalized();

  intptr_t ignore = 0;
  // Lookup the name in the library's symbols.
  Object& obj = Object::Handle(zone, lib.LookupEntry(name, &ignore));
  if (!Field::IsGetterName(name) && !Field::IsSetterName(name) &&
      (obj.IsNull() || obj.IsLibraryPrefix())) {
    String& accessor_name = String::Handle(zone);
    accessor_name = Field::LookupGetterSymbol(name);
    if (!accessor_name.IsNull()) {
      obj = lib.LookupEntry(accessor_name, &ignore);
    }
    if (obj.IsNull()) {
      accessor_name = Field::LookupSetterSymbol(name);
      if (!accessor_name.IsNull()) {
        obj = lib.LookupEntry(accessor_name, &ignore);
      }
    }
  }

  // Library prefixes are not exported.
  if (obj.IsNull() || obj.IsLibraryPrefix()) {
    // Lookup in the re-exported symbols.
    obj = lib.LookupReExport(name, trail);
    if (obj.IsNull() && !Field::IsSetterName(name)) {
      // LookupReExport() only returns objects that match the given name.
      // If there is no field/func/getter, try finding a setter.
      const String& setter_name =
          String::Handle(zone, Field::LookupSetterSymbol(name));
      if (!setter_name.IsNull()) {
        obj = lib.LookupReExport(setter_name, trail);
      }
    }
  }
  if (obj.IsNull() || HidesName(name) || obj.IsLibraryPrefix()) {
    return Object::null();
  }
  return obj.ptr();
}

NamespacePtr Namespace::New() {
  ASSERT(Object::namespace_class() != Class::null());
  return Object::Allocate<Namespace>(Heap::kOld);
}

NamespacePtr Namespace::New(const Library& target,
                            const Array& show_names,
                            const Array& hide_names,
                            const Library& owner) {
  ASSERT(show_names.IsNull() || (show_names.Length() > 0));
  ASSERT(hide_names.IsNull() || (hide_names.Length() > 0));
  const Namespace& result = Namespace::Handle(Namespace::New());
  result.untag()->set_target(target.ptr());
  result.untag()->set_show_names(show_names.ptr());
  result.untag()->set_hide_names(hide_names.ptr());
  result.untag()->set_owner(owner.ptr());
  return result.ptr();
}

KernelProgramInfoPtr KernelProgramInfo::New() {
  return Object::Allocate<KernelProgramInfo>(Heap::kOld);
}

KernelProgramInfoPtr KernelProgramInfo::New(
    const TypedDataBase& kernel_component,
    const TypedDataView& string_data,
    const TypedDataView& metadata_payloads,
    const TypedDataView& metadata_mappings,
    const TypedDataView& constants_table,
    const TypedData& string_offsets,
    const TypedData& canonical_names,
    const Array& scripts,
    const Array& libraries_cache,
    const Array& classes_cache) {
  ASSERT(kernel_component.IsExternalOrExternalView());
  ASSERT(string_data.IsExternalOrExternalView());
  ASSERT(metadata_payloads.IsExternalOrExternalView());
  ASSERT(metadata_mappings.IsExternalOrExternalView());
  ASSERT(constants_table.IsExternalOrExternalView());

  const auto& info = KernelProgramInfo::Handle(KernelProgramInfo::New());
  info.untag()->set_kernel_component(kernel_component.ptr());
  info.untag()->set_string_offsets(string_offsets.ptr());
  info.untag()->set_string_data(string_data.ptr());
  info.untag()->set_canonical_names(canonical_names.ptr());
  info.untag()->set_metadata_payloads(metadata_payloads.ptr());
  info.untag()->set_metadata_mappings(metadata_mappings.ptr());
  info.untag()->set_scripts(scripts.ptr());
  info.untag()->set_constants_table(constants_table.ptr());
  info.untag()->set_libraries_cache(libraries_cache.ptr());
  info.untag()->set_classes_cache(classes_cache.ptr());
  return info.ptr();
}

const char* KernelProgramInfo::ToCString() const {
  return "[KernelProgramInfo]";
}

ScriptPtr KernelProgramInfo::ScriptAt(intptr_t index) const {
  const Array& all_scripts = Array::Handle(scripts());
  ObjectPtr script = all_scripts.At(index);
  return Script::RawCast(script);
}

void KernelProgramInfo::set_scripts(const Array& scripts) const {
  untag()->set_scripts(scripts.ptr());
}

void KernelProgramInfo::set_constants(const Array& constants) const {
  untag()->set_constants(constants.ptr());
}

intptr_t KernelProgramInfo::KernelLibraryStartOffset(
    intptr_t library_index) const {
  const auto& blob = TypedDataBase::Handle(kernel_component());
  const intptr_t library_count =
      Utils::BigEndianToHost32(LoadUnaligned(reinterpret_cast<uint32_t*>(
          blob.DataAddr(blob.LengthInBytes() - 2 * 4))));
  ASSERT((library_index >= 0) && (library_index < library_count));
  const intptr_t library_start =
      Utils::BigEndianToHost32(LoadUnaligned(reinterpret_cast<uint32_t*>(
          blob.DataAddr(blob.LengthInBytes() -
                        (2 + 1 + (library_count - library_index)) * 4))));
  return library_start;
}

TypedDataViewPtr KernelProgramInfo::KernelLibrary(
    intptr_t library_index) const {
  ASSERT(library_index >= 0);
  const intptr_t start_offset = KernelLibraryStartOffset(library_index);
  const intptr_t end_offset = KernelLibraryEndOffset(library_index);
  const auto& component = TypedDataBase::Handle(kernel_component());
  return component.ViewFromTo(start_offset, end_offset);
}

intptr_t KernelProgramInfo::KernelLibraryEndOffset(
    intptr_t library_index) const {
  const auto& blob = TypedDataBase::Handle(kernel_component());
  const intptr_t library_count =
      Utils::BigEndianToHost32(LoadUnaligned(reinterpret_cast<uint32_t*>(
          blob.DataAddr(blob.LengthInBytes() - 2 * 4))));
  ASSERT((library_index >= 0) && (library_index < library_count));
  const intptr_t library_end = Utils::BigEndianToHost32(
      LoadUnaligned(reinterpret_cast<uint32_t*>(blob.DataAddr(
          blob.LengthInBytes() - (2 + (library_count - library_index)) * 4))));
  return library_end;
}

void KernelProgramInfo::set_constants_table(const TypedDataView& value) const {
  untag()->set_constants_table(value.ptr());
}

void KernelProgramInfo::set_libraries_cache(const Array& cache) const {
  untag()->set_libraries_cache(cache.ptr());
}

LibraryPtr KernelProgramInfo::LookupLibrary(Thread* thread,
                                            const Smi& name_index) const {
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_LIBRARY_HANDLESCOPE(thread);
  REUSABLE_OBJECT_HANDLESCOPE(thread);
  REUSABLE_SMI_HANDLESCOPE(thread);
  Array& data = thread->ArrayHandle();
  Library& result = thread->LibraryHandle();
  Object& key = thread->ObjectHandle();
  Smi& value = thread->SmiHandle();
  {
    SafepointMutexLocker ml(
        thread->isolate_group()->kernel_data_lib_cache_mutex());
    data = libraries_cache();
    ASSERT(!data.IsNull());
    IntHashMap table(&key, &value, &data);
    result ^= table.GetOrNull(name_index);
    table.Release();
  }
  return result.ptr();
}

LibraryPtr KernelProgramInfo::InsertLibrary(Thread* thread,
                                            const Smi& name_index,
                                            const Library& lib) const {
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_LIBRARY_HANDLESCOPE(thread);
  REUSABLE_OBJECT_HANDLESCOPE(thread);
  REUSABLE_SMI_HANDLESCOPE(thread);
  Array& data = thread->ArrayHandle();
  Library& result = thread->LibraryHandle();
  Object& key = thread->ObjectHandle();
  Smi& value = thread->SmiHandle();
  {
    SafepointMutexLocker ml(
        thread->isolate_group()->kernel_data_lib_cache_mutex());
    data = libraries_cache();
    ASSERT(!data.IsNull());
    IntHashMap table(&key, &value, &data);
    result ^= table.InsertOrGetValue(name_index, lib);
    set_libraries_cache(table.Release());
  }
  return result.ptr();
}

void KernelProgramInfo::set_classes_cache(const Array& cache) const {
  untag()->set_classes_cache(cache.ptr());
}

ClassPtr KernelProgramInfo::LookupClass(Thread* thread,
                                        const Smi& name_index) const {
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_CLASS_HANDLESCOPE(thread);
  REUSABLE_OBJECT_HANDLESCOPE(thread);
  REUSABLE_SMI_HANDLESCOPE(thread);
  Array& data = thread->ArrayHandle();
  Class& result = thread->ClassHandle();
  Object& key = thread->ObjectHandle();
  Smi& value = thread->SmiHandle();
  {
    SafepointMutexLocker ml(
        thread->isolate_group()->kernel_data_class_cache_mutex());
    data = classes_cache();
    ASSERT(!data.IsNull());
    IntHashMap table(&key, &value, &data);
    result ^= table.GetOrNull(name_index);
    table.Release();
  }
  return result.ptr();
}

ClassPtr KernelProgramInfo::InsertClass(Thread* thread,
                                        const Smi& name_index,
                                        const Class& klass) const {
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  REUSABLE_CLASS_HANDLESCOPE(thread);
  REUSABLE_OBJECT_HANDLESCOPE(thread);
  REUSABLE_SMI_HANDLESCOPE(thread);
  Array& data = thread->ArrayHandle();
  Class& result = thread->ClassHandle();
  Object& key = thread->ObjectHandle();
  Smi& value = thread->SmiHandle();
  {
    SafepointMutexLocker ml(
        thread->isolate_group()->kernel_data_class_cache_mutex());
    data = classes_cache();
    ASSERT(!data.IsNull());
    IntHashMap table(&key, &value, &data);
    result ^= table.InsertOrGetValue(name_index, klass);
    set_classes_cache(table.Release());
  }
  return result.ptr();
}

ErrorPtr Library::CompileAll(bool ignore_error /* = false */) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Error& error = Error::Handle(zone);
  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
      IsolateGroup::Current()->object_store()->libraries());
  Library& lib = Library::Handle(zone);
  Class& cls = Class::Handle(zone);
  for (int i = 0; i < libs.Length(); i++) {
    lib ^= libs.At(i);
    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
    while (it.HasNext()) {
      cls = it.GetNextClass();
      error = cls.EnsureIsFinalized(thread);
      if (!error.IsNull()) {
        if (ignore_error) continue;
        return error.ptr();
      }
      error = Compiler::CompileAllFunctions(cls);
      if (!error.IsNull()) {
        if (ignore_error) continue;
        return error.ptr();
      }
    }
  }

  Object& result = Object::Handle(zone);
  ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& func) {
    if (!func.HasCode()) {
      result = Compiler::CompileFunction(thread, func);
      if (result.IsError()) {
        error = Error::Cast(result).ptr();
        return false;  // Stop iteration.
      }
    }
    return true;  // Continue iteration.
  });
  return error.ptr();
}

#if !defined(DART_PRECOMPILED_RUNTIME)

ErrorPtr Library::FinalizeAllClasses() {
  Thread* thread = Thread::Current();
  ASSERT(thread->IsDartMutatorThread());
  Zone* zone = thread->zone();
  Error& error = Error::Handle(zone);
  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
      IsolateGroup::Current()->object_store()->libraries());
  Library& lib = Library::Handle(zone);
  Class& cls = Class::Handle(zone);
  for (int i = 0; i < libs.Length(); i++) {
    lib ^= libs.At(i);
    if (!lib.Loaded()) {
      String& uri = String::Handle(zone, lib.url());
      String& msg = String::Handle(
          zone,
          String::NewFormatted("Library '%s' is not loaded. "
                               "Did you forget to call Dart_FinalizeLoading?",
                               uri.ToCString()));
      return ApiError::New(msg);
    }
    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
    while (it.HasNext()) {
      cls = it.GetNextClass();
      error = cls.EnsureIsFinalized(thread);
      if (!error.IsNull()) {
        return error.ptr();
      }
    }
  }
  return Error::null();
}

#endif  // !defined(DART_PRECOMPILED_RUNTIME)

// Return Function::null() if function does not exist in libs.
FunctionPtr Library::GetFunction(const Library& lib,
                                 const char* class_name,
                                 const char* function_name) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Function& func = Function::Handle(zone);
  String& class_str = String::Handle(zone);
  String& func_str = String::Handle(zone);
  Class& cls = Class::Handle(zone);
  if (strcmp(class_name, "::") == 0) {
    cls = lib.toplevel_class();
  } else {
    class_str = String::New(class_name);
    cls = lib.LookupClassAllowPrivate(class_str);
  }
  if (!cls.IsNull()) {
    if (cls.EnsureIsFinalized(thread) == Error::null()) {
      func_str = String::New(function_name);
      if (function_name[0] == '.') {
        func_str = String::Concat(class_str, func_str);
      }
      func = cls.LookupFunctionAllowPrivate(func_str);
    }
  }
  return func.ptr();
}

#if defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME)
void Library::CheckFunctionFingerprints() {
  Library& lib = Library::Handle();
  Function& func = Function::Handle();
  bool fingerprints_match = true;

#define CHECK_FINGERPRINTS_INNER(library, class_name, function_name, dest, fp, \
                                 kind)                                         \
  lib = Library::library();                                                    \
  func = Library::GetFunction(lib, #class_name, #function_name);               \
  if (func.IsNull()) {                                                         \
    fingerprints_match = false;                                                \
    OS::PrintErr("Function not found %s.%s\n", #class_name, #function_name);   \
  } else {                                                                     \
    fingerprints_match =                                                       \
        func.CheckSourceFingerprint(fp, kind) && fingerprints_match;           \
  }

#define CHECK_FINGERPRINTS(library, class_name, function_name, dest, fp)       \
  CHECK_FINGERPRINTS_INNER(library, class_name, function_name, dest, fp,       \
                           nullptr)
#define CHECK_FINGERPRINTS_ASM_INTRINSIC(library, class_name, function_name,   \
                                         dest, fp)                             \
  CHECK_FINGERPRINTS_INNER(library, class_name, function_name, dest, fp,       \
                           "asm-intrinsic")
#define CHECK_FINGERPRINTS_GRAPH_INTRINSIC(library, class_name, function_name, \
                                           dest, fp)                           \
  CHECK_FINGERPRINTS_INNER(library, class_name, function_name, dest, fp,       \
                           "graph-intrinsic")
#define CHECK_FINGERPRINTS_OTHER(library, class_name, function_name, dest, fp) \
  CHECK_FINGERPRINTS_INNER(library, class_name, function_name, dest, fp,       \
                           "other")

  POLYMORPHIC_TARGET_LIST(CHECK_FINGERPRINTS)
  ASM_INTRINSICS_LIST(CHECK_FINGERPRINTS_ASM_INTRINSIC)
  GRAPH_INTRINSICS_LIST(CHECK_FINGERPRINTS_GRAPH_INTRINSIC)
  OTHER_RECOGNIZED_LIST(CHECK_FINGERPRINTS_OTHER)

#undef CHECK_FINGERPRINTS_INNER
#undef CHECK_FINGERPRINTS
#undef CHECK_FINGERPRINTS_ASM_INTRINSIC
#undef CHECK_FINGERPRINTS_GRAPH_INTRINSIC
#undef CHECK_FINGERPRINTS_OTHER

#define CHECK_FACTORY_FINGERPRINTS(symbol, library, class_name, factory_name,  \
                                   cid, fp)                                    \
  lib = Library::library();                                                    \
  func = GetFunction(lib, #class_name, #factory_name);                         \
  if (func.IsNull()) {                                                         \
    fingerprints_match = false;                                                \
    OS::PrintErr("Function not found %s.%s.%s\n", #library, #class_name,       \
                 #factory_name);                                               \
  } else {                                                                     \
    fingerprints_match =                                                       \
        func.CheckSourceFingerprint(fp) && fingerprints_match;                 \
  }

  RECOGNIZED_LIST_FACTORY_LIST(CHECK_FACTORY_FINGERPRINTS);

#undef CHECK_FACTORY_FINGERPRINTS

  if (!fingerprints_match) {
    // Private names are mangled. Mangling depends on Library::private_key_.
    // If registering a new bootstrap library, add at the end.
    FATAL(
        "FP mismatch while recognizing methods. If the behavior of "
        "these functions has changed, then changes are also needed in "
        "the VM's compiler. Otherwise the fingerprint can simply be "
        "updated in recognized_methods_list.h\n");
  }
}
#endif  // defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME).

InstructionsPtr Instructions::New(intptr_t size,
                                  bool has_monomorphic_entry,
                                  bool should_be_aligned) {
  ASSERT(size >= 0);
  ASSERT(Object::instructions_class() != Class::null());
  if (size < 0 || size > kMaxElements) {
    // This should be caught before we reach here.
    FATAL("Fatal error in Instructions::New: invalid size %" Pd "\n", size);
  }
  Instructions& result = Instructions::Handle();
  {
    auto raw = Object::Allocate<Instructions>(Heap::kCode, size);
    NoSafepointScope no_safepoint;
    result = raw;
    result.SetSize(size);
    // Set this within the NoSafepointScope as well since it is contained in
    // the same bitfield as the size.
    result.SetHasMonomorphicEntry(has_monomorphic_entry);
    result.SetShouldBeAligned(should_be_aligned);
  }
  ASSERT(result.stats() == nullptr);
  return result.ptr();
}

const char* Instructions::ToCString() const {
  return "Instructions";
}

CodeStatistics* Instructions::stats() const {
#if defined(DART_PRECOMPILER)
  return reinterpret_cast<CodeStatistics*>(
      Thread::Current()->heap()->GetPeer(ptr()));
#else
  return nullptr;
#endif
}

void Instructions::set_stats(CodeStatistics* stats) const {
#if defined(DART_PRECOMPILER)
  Thread::Current()->heap()->SetPeer(ptr(), stats);
#endif
}

const char* InstructionsSection::ToCString() const {
  return "InstructionsSection";
}

void InstructionsTable::set_length(intptr_t value) const {
  StoreNonPointer(&untag()->length_, value);
}

void InstructionsTable::set_start_pc(uword value) const {
  StoreNonPointer(&untag()->start_pc_, value);
}

void InstructionsTable::set_end_pc(uword value) const {
  StoreNonPointer(&untag()->end_pc_, value);
}

void InstructionsTable::set_code_objects(const Array& value) const {
  untag()->set_code_objects(value.ptr());
}

void InstructionsTable::set_rodata(uword value) const {
  StoreNonPointer(
      &untag()->rodata_,
      reinterpret_cast<const UntaggedInstructionsTable::Data*>(value));
}

InstructionsTablePtr InstructionsTable::New(intptr_t length,
                                            uword start_pc,
                                            uword end_pc,
                                            uword rodata) {
  ASSERT(Object::instructions_table_class() != Class::null());
  ASSERT(length >= 0);
  ASSERT(start_pc <= end_pc);
  auto* const zone = Thread::Current()->zone();
  const Array& code_objects =
      (length == 0) ? Object::empty_array()
                    : Array::Handle(zone, Array::New(length, Heap::kOld));
  const auto& result = InstructionsTable::Handle(
      zone, Object::Allocate<InstructionsTable>(Heap::kOld));
  result.set_code_objects(code_objects);
  result.set_length(length);
  result.set_start_pc(start_pc);
  result.set_end_pc(end_pc);
  result.set_rodata(rodata);
  return result.ptr();
}

void InstructionsTable::SetCodeAt(intptr_t index, CodePtr code) const {
  ASSERT((0 <= index) &&
         (index < Smi::Value(code_objects()->untag()->length())));
  code_objects()->untag()->set_element(index, code);
}

bool InstructionsTable::ContainsPc(InstructionsTablePtr table, uword pc) {
  return (InstructionsTable::start_pc(table) <= pc) &&
         (pc < InstructionsTable::end_pc(table));
}

uint32_t InstructionsTable::ConvertPcToOffset(InstructionsTablePtr table,
                                              uword pc) {
  ASSERT(InstructionsTable::ContainsPc(table, pc));
  const uint32_t pc_offset =
      static_cast<uint32_t>(pc - InstructionsTable::start_pc(table));
  ASSERT(InstructionsTable::start_pc(table) + pc_offset == pc);  // No overflow.
  return pc_offset;
}

intptr_t InstructionsTable::FindEntry(InstructionsTablePtr table,
                                      uword pc,
                                      intptr_t start_index /* = 0 */) {
  // This can run in the middle of GC and must not allocate handles.
  NoSafepointScope no_safepoint;
  if (!InstructionsTable::ContainsPc(table, pc)) return -1;
  const uint32_t pc_offset = InstructionsTable::ConvertPcToOffset(table, pc);

  const auto rodata = table.untag()->rodata_;
  const auto entries = rodata->entries();
  intptr_t lo = start_index;
  intptr_t hi = rodata->length - 1;
  while (lo <= hi) {
    intptr_t mid = (hi - lo + 1) / 2 + lo;
    ASSERT(mid >= lo);
    ASSERT(mid <= hi);
    if (pc_offset < entries[mid].pc_offset) {
      hi = mid - 1;
    } else if ((mid != hi) && (pc_offset >= entries[mid + 1].pc_offset)) {
      lo = mid + 1;
    } else {
      return mid;
    }
  }
  return -1;
}

const UntaggedCompressedStackMaps::Payload*
InstructionsTable::GetCanonicalStackMap(InstructionsTablePtr table) {
  const auto rodata = table.untag()->rodata_;
  return rodata->canonical_stack_map_entries_offset != 0
             ? rodata->StackMapAt(rodata->canonical_stack_map_entries_offset)
             : nullptr;
}

const UntaggedCompressedStackMaps::Payload* InstructionsTable::FindStackMap(
    InstructionsTablePtr table,
    uword pc,
    uword* start_pc) {
  // This can run in the middle of GC and must not allocate handles.
  NoSafepointScope no_safepoint;
  const intptr_t idx = FindEntry(table, pc);
  if (idx != -1) {
    const auto rodata = table.untag()->rodata_;
    const auto entries = rodata->entries();
    *start_pc = InstructionsTable::start_pc(table) + entries[idx].pc_offset;
    return rodata->StackMapAt(entries[idx].stack_map_offset);
  }
  return nullptr;
}

CodePtr InstructionsTable::FindCode(InstructionsTablePtr table, uword pc) {
  // This can run in the middle of GC and must not allocate handles.
  NoSafepointScope no_safepoint;
  if (!InstructionsTable::ContainsPc(table, pc)) return Code::null();

  const auto rodata = table.untag()->rodata_;

  const auto pc_offset = InstructionsTable::ConvertPcToOffset(table, pc);

  if (pc_offset <= rodata->entries()[rodata->first_entry_with_code].pc_offset) {
    return StubCode::UnknownDartCode().ptr();
  }

  const auto idx =
      FindEntry(table, pc, table.untag()->rodata_->first_entry_with_code);
  if (idx != -1) {
    const intptr_t code_index = idx - rodata->first_entry_with_code;
    ASSERT(code_index >= 0);
    ASSERT(code_index <
           Smi::Value(table.untag()->code_objects()->untag()->length()));
    ObjectPtr result =
        table.untag()->code_objects()->untag()->element(code_index);
    ASSERT(result->IsCode());
    // Note: can't use Code::RawCast(...) here because it allocates handles
    // in DEBUG mode.
    return static_cast<CodePtr>(result);
  }

  return Code::null();
}

uword InstructionsTable::EntryPointAt(intptr_t code_index) const {
  ASSERT(0 <= code_index);
  ASSERT(code_index < static_cast<intptr_t>(rodata()->length));
  return InstructionsTable::start_pc(this->ptr()) +
         rodata()->entries()[code_index].pc_offset;
}

const char* InstructionsTable::ToCString() const {
  return "InstructionsTable";
}

ObjectPoolPtr ObjectPool::New(intptr_t len) {
  ASSERT(Object::object_pool_class() != Class::null());
  if (len < 0 || len > kMaxElements) {
    // This should be caught before we reach here.
    FATAL("Fatal error in ObjectPool::New: invalid length %" Pd "\n", len);
  }
  // We only verify the entry bits in DEBUG, so only allocate a handle there.
  DEBUG_ONLY(auto& result = ObjectPool::Handle());
  auto raw = Object::Allocate<ObjectPool>(Heap::kOld, len);
  NoSafepointScope no_safepoint;
  raw->untag()->length_ = len;
#if defined(DEBUG)
  result = raw;
  for (intptr_t i = 0; i < len; i++) {
    // Verify that InitializeObject() already set the payload as expected.
    ASSERT_EQUAL(result.PatchableAt(i), ObjectPool::Patchability::kPatchable);
    ASSERT_EQUAL(result.TypeAt(i), ObjectPool::EntryType::kImmediate);
    ASSERT_EQUAL(result.RawValueAt(i), 0);
  }
#endif
  return raw;
}

#if !defined(DART_PRECOMPILED_RUNTIME)
ObjectPoolPtr ObjectPool::NewFromBuilder(
    const compiler::ObjectPoolBuilder& builder) {
  const intptr_t len = builder.CurrentLength();
  if (len == 0) {
    return Object::empty_object_pool().ptr();
  }
  const ObjectPool& result = ObjectPool::Handle(ObjectPool::New(len));
  for (intptr_t i = 0; i < len; i++) {
    auto entry = builder.EntryAt(i);
    auto type = entry.type();
    auto patchable = entry.patchable();
    auto snapshot_behavior = entry.snapshot_behavior();
    result.SetTypeAt(i, type, patchable, snapshot_behavior);
    if (type == EntryType::kTaggedObject) {
      result.SetObjectAt(i, *entry.obj_);
    } else {
#if defined(TARGET_ARCH_IS_32_BIT)
      ASSERT(type != EntryType::kImmediate64);
#endif
      ASSERT(type != EntryType::kImmediate128);
      result.SetRawValueAt(i, entry.imm_);
    }
  }
  return result.ptr();
}

void ObjectPool::CopyInto(compiler::ObjectPoolBuilder* builder) const {
  ASSERT(builder->CurrentLength() == 0);
  for (intptr_t i = 0; i < Length(); i++) {
    auto type = TypeAt(i);
    auto patchable = PatchableAt(i);
    auto snapshot_behavior = SnapshotBehaviorAt(i);
    switch (type) {
      case compiler::ObjectPoolBuilderEntry::kTaggedObject: {
        compiler::ObjectPoolBuilderEntry entry(&Object::ZoneHandle(ObjectAt(i)),
                                               patchable, snapshot_behavior);
        builder->AddObject(entry);
        break;
      }
      case compiler::ObjectPoolBuilderEntry::kImmediate:
      case compiler::ObjectPoolBuilderEntry::kNativeFunction: {
        compiler::ObjectPoolBuilderEntry entry(RawValueAt(i), type, patchable,
                                               snapshot_behavior);
        builder->AddObject(entry);
        break;
      }
      default:
        UNREACHABLE();
    }
  }
  ASSERT(builder->CurrentLength() == Length());
}
#endif

const char* ObjectPool::ToCString() const {
  Zone* zone = Thread::Current()->zone();
  return zone->PrintToString("ObjectPool len:%" Pd, Length());
}

void ObjectPool::DebugPrint() const {
  THR_Print("ObjectPool len:%" Pd " {\n", Length());
  for (intptr_t i = 0; i < Length(); i++) {
#if defined(DART_PRECOMPILED_RUNTIME)
    intptr_t offset = ObjectPool::element_offset(i);
#else
    intptr_t offset = compiler::target::ObjectPool::element_offset(i);
#endif
#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
    THR_Print("  %" Pd "(pp) ", offset);  // PP is untagged
#elif defined(TARGET_ARCH_ARM64)
    THR_Print("  [pp, #%" Pd "] ", offset);  // PP is untagged
#elif defined(TARGET_ARCH_ARM32)
    THR_Print("  [pp, #%" Pd "] ", offset - kHeapObjectTag);  // PP is tagged
#else
    THR_Print("  [pp+0x%" Px "] ", offset - kHeapObjectTag);  // PP is tagged
#endif
    if (TypeAt(i) == EntryType::kTaggedObject) {
      const Object& obj = Object::Handle(ObjectAt(i));
      THR_Print("%s (obj)\n", obj.ToCString());
    } else if (TypeAt(i) == EntryType::kNativeFunction) {
      uword pc = RawValueAt(i);
      uintptr_t start = 0;
      const char* name = NativeSymbolResolver::LookupSymbolName(pc, &start);
      const char* dso_name;
      uword dso_base;
      if (name != nullptr) {
        THR_Print("%s (native function)\n", name);
        NativeSymbolResolver::FreeSymbolName(name);
      } else if (NativeSymbolResolver::LookupSharedObject(pc, &dso_base,
                                                          &dso_name)) {
        uword dso_offset = pc - dso_base;
        THR_Print("%s+0x%" Px " (native function)\n", dso_name, dso_offset);
        NativeSymbolResolver::FreeSymbolName(dso_name);
      } else {
        THR_Print("0x%" Px " (native function)\n", pc);
      }
    } else {
      THR_Print("0x%" Px " (raw)\n", RawValueAt(i));
    }
  }
  THR_Print("}\n");
}

intptr_t PcDescriptors::Length() const {
  return untag()->length_;
}

void PcDescriptors::SetLength(intptr_t value) const {
  StoreNonPointer(&untag()->length_, value);
}

void PcDescriptors::CopyData(const void* bytes, intptr_t size) {
  NoSafepointScope no_safepoint;
  uint8_t* data = UnsafeMutableNonPointer(&untag()->data()[0]);
  // We're guaranteed these memory spaces do not overlap.
  memcpy(data, bytes, size);  // NOLINT
}

PcDescriptorsPtr PcDescriptors::New(const void* delta_encoded_data,
                                    intptr_t size) {
  ASSERT(Object::pc_descriptors_class() != Class::null());
  Thread* thread = Thread::Current();
  PcDescriptors& result = PcDescriptors::Handle(thread->zone());
  {
    auto raw = Object::Allocate<PcDescriptors>(Heap::kOld, size);
    NoSafepointScope no_safepoint;
    result = raw;
    result.SetLength(size);
  }
  result.CopyData(delta_encoded_data, size);
  return result.ptr();
}

PcDescriptorsPtr PcDescriptors::New(intptr_t length) {
  ASSERT(Object::pc_descriptors_class() != Class::null());
  Thread* thread = Thread::Current();
  PcDescriptors& result = PcDescriptors::Handle(thread->zone());
  {
    auto raw = Object::Allocate<PcDescriptors>(Heap::kOld, length);
    NoSafepointScope no_safepoint;
    result = raw;
    result.SetLength(length);
  }
  return result.ptr();
}

const char* PcDescriptors::KindAsStr(UntaggedPcDescriptors::Kind kind) {
  switch (kind) {
    case UntaggedPcDescriptors::kDeopt:
      return "deopt        ";
    case UntaggedPcDescriptors::kIcCall:
      return "ic-call";
    case UntaggedPcDescriptors::kUnoptStaticCall:
      return "unopt-call";
    case UntaggedPcDescriptors::kRuntimeCall:
      return "runtime-call";
    case UntaggedPcDescriptors::kOsrEntry:
      return "osr-entry";
    case UntaggedPcDescriptors::kRewind:
      return "rewind";
    case UntaggedPcDescriptors::kBSSRelocation:
      return "bss reloc";
    case UntaggedPcDescriptors::kOther:
      return "other";
    case UntaggedPcDescriptors::kAnyKind:
      UNREACHABLE();
      break;
  }
  UNREACHABLE();
  return "";
}

void PcDescriptors::WriteToBuffer(BaseTextBuffer* buffer, uword base) const {
  // 4 bits per hex digit.
  const int addr_width = kBitsPerWord / 4;
  // "*" in a printf format specifier tells it to read the field width from
  // the printf argument list.
  buffer->Printf(
      "%-*s  kind           deopt-id  tok-ix        try-ix yield-idx\n",
      addr_width, "pc");
  Iterator iter(*this, UntaggedPcDescriptors::kAnyKind);
  while (iter.MoveNext()) {
    buffer->Printf("%#-*" Px "  %-13s  % 8" Pd "  %-10s  % 8" Pd "  % 8" Pd
                   "\n",
                   addr_width, base + iter.PcOffset(), KindAsStr(iter.Kind()),
                   iter.DeoptId(), iter.TokenPos().ToCString(), iter.TryIndex(),
                   iter.YieldIndex());
  }
}

const char* PcDescriptors::ToCString() const {
  if (Length() == 0) {
    return "empty PcDescriptors";
  }
  ZoneTextBuffer buffer(Thread::Current()->zone());
  WriteToBuffer(&buffer, /*base=*/0);
  return buffer.buffer();
}

// Verify assumptions (in debug mode only).
// - No two deopt descriptors have the same deoptimization id.
// - No two ic-call descriptors have the same deoptimization id (type feedback).
// A function without unique ids is marked as non-optimizable (e.g., because of
// finally blocks).
void PcDescriptors::Verify(const Function& function) const {
#if defined(DEBUG)
  // Only check ids for unoptimized code that is optimizable.
  if (!function.IsOptimizable()) {
    return;
  }
  intptr_t max_deopt_id = 0;
  Iterator max_iter(
      *this, UntaggedPcDescriptors::kDeopt | UntaggedPcDescriptors::kIcCall);
  while (max_iter.MoveNext()) {
    if (max_iter.DeoptId() > max_deopt_id) {
      max_deopt_id = max_iter.DeoptId();
    }
  }

  Zone* zone = Thread::Current()->zone();
  BitVector* deopt_ids = new (zone) BitVector(zone, max_deopt_id + 1);
  BitVector* iccall_ids = new (zone) BitVector(zone, max_deopt_id + 1);
  Iterator iter(*this,
                UntaggedPcDescriptors::kDeopt | UntaggedPcDescriptors::kIcCall);
  while (iter.MoveNext()) {
    // 'deopt_id' is set for kDeopt and kIcCall and must be unique for one kind.
    if (DeoptId::IsDeoptAfter(iter.DeoptId())) {
      // TODO(vegorov): some instructions contain multiple calls and have
      // multiple "after" targets recorded. Right now it is benign but might
      // lead to issues in the future. Fix that and enable verification.
      continue;
    }
    if (iter.Kind() == UntaggedPcDescriptors::kDeopt) {
      ASSERT(!deopt_ids->Contains(iter.DeoptId()));
      deopt_ids->Add(iter.DeoptId());
    } else {
      ASSERT(!iccall_ids->Contains(iter.DeoptId()));
      iccall_ids->Add(iter.DeoptId());
    }
  }
#endif  // DEBUG
}

void CodeSourceMap::SetLength(intptr_t value) const {
  StoreNonPointer(&untag()->length_, value);
}

CodeSourceMapPtr CodeSourceMap::New(intptr_t length) {
  ASSERT(Object::code_source_map_class() != Class::null());
  Thread* thread = Thread::Current();
  CodeSourceMap& result = CodeSourceMap::Handle(thread->zone());
  {
    auto raw = Object::Allocate<CodeSourceMap>(Heap::kOld, length);
    NoSafepointScope no_safepoint;
    result = raw;
    result.SetLength(length);
  }
  return result.ptr();
}

const char* CodeSourceMap::ToCString() const {
  return "CodeSourceMap";
}

uword CompressedStackMaps::Hash() const {
  NoSafepointScope scope;
  uint8_t* data = UnsafeMutableNonPointer(&untag()->payload()->data()[0]);
  uint8_t* end = data + payload_size();
  uint32_t hash = payload_size();
  for (uint8_t* cursor = data; cursor < end; cursor++) {
    hash = CombineHashes(hash, *cursor);
  }
  return FinalizeHash(hash, kHashBits);
}

void CompressedStackMaps::WriteToBuffer(BaseTextBuffer* buffer,
                                        uword base,
                                        const char* separator) const {
  auto it = iterator(Thread::Current());
  bool first_entry = true;
  while (it.MoveNext()) {
    if (!first_entry) {
      buffer->AddString(separator);
    }
    buffer->Printf("0x%.8" Px ": ", base + it.pc_offset());
    for (intptr_t i = 0, n = it.Length(); i < n; i++) {
      buffer->AddString(it.IsObject(i) ? "1" : "0");
    }
    first_entry = false;
  }
}

CompressedStackMaps::Iterator<CompressedStackMaps>
CompressedStackMaps::iterator(Thread* thread) const {
  return Iterator<CompressedStackMaps>(
      *this, CompressedStackMaps::Handle(
                 thread->zone(), thread->isolate_group()
                                     ->object_store()
                                     ->canonicalized_stack_map_entries()));
}

CompressedStackMapsPtr CompressedStackMaps::New(const void* payload,
                                                intptr_t size,
                                                bool is_global_table,
                                                bool uses_global_table) {
  ASSERT(Object::compressed_stackmaps_class() != Class::null());
  // We don't currently allow both flags to be true.
  ASSERT(!is_global_table || !uses_global_table);
  // The canonical empty instance should be used instead.
  ASSERT(size != 0);

  if (!UntaggedCompressedStackMaps::SizeField::is_valid(size)) {
    FATAL(
        "Fatal error in CompressedStackMaps::New: "
        "invalid payload size %" Pu "\n",
        size);
  }

  auto& result = CompressedStackMaps::Handle();
  {
    // CompressedStackMaps data objects are associated with a code object,
    // allocate them in old generation.
    auto raw = Object::Allocate<CompressedStackMaps>(Heap::kOld, size);
    NoSafepointScope no_safepoint;
    result = raw;
    result.untag()->payload()->set_flags_and_size(
        UntaggedCompressedStackMaps::GlobalTableBit::encode(is_global_table) |
        UntaggedCompressedStackMaps::UsesTableBit::encode(uses_global_table) |
        UntaggedCompressedStackMaps::SizeField::encode(size));
    // Perform the copy under the NoSafepointScope since it uses a raw pointer
    // to the payload, and so the object should not move during the copy.
    auto cursor =
        result.UnsafeMutableNonPointer(result.untag()->payload()->data());
    memcpy(cursor, payload, size);  // NOLINT
  }

  ASSERT(!result.IsGlobalTable() || !result.UsesGlobalTable());

  return result.ptr();
}

const char* CompressedStackMaps::ToCString() const {
  ASSERT(!IsGlobalTable());
  if (payload_size() == 0) {
    return "CompressedStackMaps()";
  }
  auto const t = Thread::Current();
  ZoneTextBuffer buffer(t->zone(), 100);
  buffer.AddString("CompressedStackMaps(");
  WriteToBuffer(&buffer, /*base=*/0, ", ");
  buffer.AddString(")");
  return buffer.buffer();
}

StringPtr LocalVarDescriptors::GetName(intptr_t var_index) const {
  ASSERT(var_index < Length());
  ASSERT(Object::Handle(ptr()->untag()->name(var_index)).IsString());
  return ptr()->untag()->name(var_index);
}

void LocalVarDescriptors::SetVar(
    intptr_t var_index,
    const String& name,
    UntaggedLocalVarDescriptors::VarInfo* info) const {
  ASSERT(var_index < Length());
  ASSERT(!name.IsNull());
  ptr()->untag()->set_name(var_index, name.ptr());
  ptr()->untag()->data()[var_index] = *info;
}

void LocalVarDescriptors::GetInfo(
    intptr_t var_index,
    UntaggedLocalVarDescriptors::VarInfo* info) const {
  ASSERT(var_index < Length());
  *info = ptr()->untag()->data()[var_index];
}

static int PrintVarInfo(char* buffer,
                        int len,
                        intptr_t i,
                        const String& var_name,
                        const UntaggedLocalVarDescriptors::VarInfo& info) {
  const UntaggedLocalVarDescriptors::VarInfoKind kind = info.kind();
  const int32_t index = info.index();
  if (kind == UntaggedLocalVarDescriptors::kContextLevel) {
    return Utils::SNPrint(buffer, len,
                          "%2" Pd
                          " %-13s level=%-3d"
                          " begin=%-3d end=%d\n",
                          i, LocalVarDescriptors::KindToCString(kind), index,
                          static_cast<int>(info.begin_pos.Pos()),
                          static_cast<int>(info.end_pos.Pos()));
  } else if (kind == UntaggedLocalVarDescriptors::kContextVar) {
    return Utils::SNPrint(
        buffer, len,
        "%2" Pd
        " %-13s level=%-3d index=%-3d"
        " begin=%-3d end=%-3d name=%s\n",
        i, LocalVarDescriptors::KindToCString(kind), info.scope_id, index,
        static_cast<int>(info.begin_pos.Pos()),
        static_cast<int>(info.end_pos.Pos()), var_name.ToCString());
  } else {
    return Utils::SNPrint(
        buffer, len,
        "%2" Pd
        " %-13s scope=%-3d index=%-3d"
        " begin=%-3d end=%-3d name=%s\n",
        i, LocalVarDescriptors::KindToCString(kind), info.scope_id, index,
        static_cast<int>(info.begin_pos.Pos()),
        static_cast<int>(info.end_pos.Pos()), var_name.ToCString());
  }
}

const char* LocalVarDescriptors::ToCString() const {
  if (IsNull()) {
    return "LocalVarDescriptors: null";
  }
  if (Length() == 0) {
    return "empty LocalVarDescriptors";
  }
  intptr_t len = 1;  // Trailing '\0'.
  String& var_name = String::Handle();
  for (intptr_t i = 0; i < Length(); i++) {
    UntaggedLocalVarDescriptors::VarInfo info;
    var_name = GetName(i);
    GetInfo(i, &info);
    len += PrintVarInfo(nullptr, 0, i, var_name, info);
  }
  char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
  buffer[0] = '\0';
  intptr_t num_chars = 0;
  for (intptr_t i = 0; i < Length(); i++) {
    UntaggedLocalVarDescriptors::VarInfo info;
    var_name = GetName(i);
    GetInfo(i, &info);
    num_chars += PrintVarInfo((buffer + num_chars), (len - num_chars), i,
                              var_name, info);
  }
  return buffer;
}

const char* LocalVarDescriptors::KindToCString(
    UntaggedLocalVarDescriptors::VarInfoKind kind) {
  switch (kind) {
    case UntaggedLocalVarDescriptors::kStackVar:
      return "StackVar";
    case UntaggedLocalVarDescriptors::kContextVar:
      return "ContextVar";
    case UntaggedLocalVarDescriptors::kContextLevel:
      return "ContextLevel";
    case UntaggedLocalVarDescriptors::kSavedCurrentContext:
      return "CurrentCtx";
    default:
      UNIMPLEMENTED();
      return nullptr;
  }
}

LocalVarDescriptorsPtr LocalVarDescriptors::New(intptr_t num_variables) {
  ASSERT(Object::var_descriptors_class() != Class::null());
  if (num_variables < 0 || num_variables > kMaxElements) {
    // This should be caught before we reach here.
    FATAL(
        "Fatal error in LocalVarDescriptors::New: "
        "invalid num_variables %" Pd ". Maximum is: %d\n",
        num_variables, UntaggedLocalVarDescriptors::VarInfo::kMaxIndex);
  }
  auto raw = Object::Allocate<LocalVarDescriptors>(Heap::kOld, num_variables);
  NoSafepointScope no_safepoint;
  raw->untag()->num_entries_ = num_variables;
  return raw;
}

intptr_t LocalVarDescriptors::Length() const {
  return untag()->num_entries_;
}

intptr_t ExceptionHandlers::num_entries() const {
  return untag()->num_entries();
}

bool ExceptionHandlers::has_async_handler() const {
  return UntaggedExceptionHandlers::AsyncHandlerBit::decode(
      untag()->packed_fields_);
}

void ExceptionHandlers::set_has_async_handler(bool value) const {
  StoreNonPointer(&untag()->packed_fields_,
                  UntaggedExceptionHandlers::AsyncHandlerBit::update(
                      value, untag()->packed_fields_));
}

void ExceptionHandlers::SetHandlerInfo(intptr_t try_index,
                                       intptr_t outer_try_index,
                                       uword handler_pc_offset,
                                       bool needs_stacktrace,
                                       bool has_catch_all,
                                       bool is_generated) const {
  ASSERT((try_index >= 0) && (try_index < num_entries()));
  NoSafepointScope no_safepoint;
  ExceptionHandlerInfo* info =
      UnsafeMutableNonPointer(&untag()->data()[try_index]);
  info->outer_try_index = outer_try_index;
  // Some C compilers warn about the comparison always being true when using <=
  // due to limited range of data type.
  ASSERT((handler_pc_offset == static_cast<uword>(kMaxUint32)) ||
         (handler_pc_offset < static_cast<uword>(kMaxUint32)));
  info->handler_pc_offset = handler_pc_offset;
  info->needs_stacktrace = static_cast<int8_t>(needs_stacktrace);
  info->has_catch_all = static_cast<int8_t>(has_catch_all);
  info->is_generated = static_cast<int8_t>(is_generated);
}

void ExceptionHandlers::GetHandlerInfo(intptr_t try_index,
                                       ExceptionHandlerInfo* info) const {
  ASSERT((try_index >= 0) && (try_index < num_entries()));
  ASSERT(info != nullptr);
  *info = untag()->data()[try_index];
}

uword ExceptionHandlers::HandlerPCOffset(intptr_t try_index) const {
  ASSERT((try_index >= 0) && (try_index < num_entries()));
  return untag()->data()[try_index].handler_pc_offset;
}

intptr_t ExceptionHandlers::OuterTryIndex(intptr_t try_index) const {
  ASSERT((try_index >= 0) && (try_index < num_entries()));
  return untag()->data()[try_index].outer_try_index;
}

bool ExceptionHandlers::NeedsStackTrace(intptr_t try_index) const {
  ASSERT((try_index >= 0) && (try_index < num_entries()));
  return untag()->data()[try_index].needs_stacktrace != 0;
}

bool ExceptionHandlers::IsGenerated(intptr_t try_index) const {
  ASSERT((try_index >= 0) && (try_index < num_entries()));
  return untag()->data()[try_index].is_generated != 0;
}

bool ExceptionHandlers::HasCatchAll(intptr_t try_index) const {
  ASSERT((try_index >= 0) && (try_index < num_entries()));
  return untag()->data()[try_index].has_catch_all != 0;
}

void ExceptionHandlers::SetHandledTypes(intptr_t try_index,
                                        const Array& handled_types) const {
  ASSERT((try_index >= 0) && (try_index < num_entries()));
  ASSERT(!handled_types.IsNull());
  const Array& handled_types_data =
      Array::Handle(untag()->handled_types_data());
  handled_types_data.SetAt(try_index, handled_types);
}

ArrayPtr ExceptionHandlers::GetHandledTypes(intptr_t try_index) const {
  ASSERT((try_index >= 0) && (try_index < num_entries()));
  Array& array = Array::Handle(untag()->handled_types_data());
  array ^= array.At(try_index);
  return array.ptr();
}

void ExceptionHandlers::set_handled_types_data(const Array& value) const {
  untag()->set_handled_types_data(value.ptr());
}

ExceptionHandlersPtr ExceptionHandlers::New(intptr_t num_handlers) {
  ASSERT(Object::exception_handlers_class() != Class::null());
  if ((num_handlers < 0) || (num_handlers >= kMaxHandlers)) {
    FATAL(
        "Fatal error in ExceptionHandlers::New(): "
        "invalid num_handlers %" Pd "\n",
        num_handlers);
  }
  const Array& handled_types_data =
      (num_handlers == 0) ? Object::empty_array()
                          : Array::Handle(Array::New(num_handlers, Heap::kOld));
  return ExceptionHandlers::New(handled_types_data);
}

ExceptionHandlersPtr ExceptionHandlers::New(const Array& handled_types_data) {
  ASSERT(Object::exception_handlers_class() != Class::null());
  const intptr_t num_handlers = handled_types_data.Length();
  if ((num_handlers < 0) || (num_handlers >= kMaxHandlers)) {
    FATAL(
        "Fatal error in ExceptionHandlers::New(): "
        "invalid num_handlers %" Pd "\n",
        num_handlers);
  }
  ExceptionHandlers& result = ExceptionHandlers::Handle();
  {
    auto raw = Object::Allocate<ExceptionHandlers>(Heap::kOld, num_handlers);
    NoSafepointScope no_safepoint;
    result = raw;
    result.untag()->packed_fields_ =
        UntaggedExceptionHandlers::NumEntriesBits::encode(num_handlers);
  }
  result.set_handled_types_data(handled_types_data);
  return result.ptr();
}

void ExceptionHandlers::WriteToBuffer(BaseTextBuffer* buffer,
                                      uword base) const {
  auto& handled_types = Array::Handle();
  auto& type = AbstractType::Handle();
  ExceptionHandlerInfo info;
  for (intptr_t i = 0; i < num_entries(); i++) {
    GetHandlerInfo(i, &info);
    handled_types = GetHandledTypes(i);
    const intptr_t num_types =
        handled_types.IsNull() ? 0 : handled_types.Length();
    buffer->Printf("%" Pd " => %#" Px "  (%" Pd " types) (outer %d)%s%s\n", i,
                   base + info.handler_pc_offset, num_types,
                   info.outer_try_index,
                   ((info.needs_stacktrace != 0) ? " (needs stack trace)" : ""),
                   ((info.is_generated != 0) ? " (generated)" : ""));
    for (int k = 0; k < num_types; k++) {
      type ^= handled_types.At(k);
      ASSERT(!type.IsNull());
      buffer->Printf("  %d. %s\n", k, type.ToCString());
    }
  }
  if (has_async_handler()) {
    buffer->AddString("<async handler>\n");
  }
}

const char* ExceptionHandlers::ToCString() const {
  if (num_entries() == 0) {
    return has_async_handler()
               ? "empty ExceptionHandlers (with <async handler>)"
               : "empty ExceptionHandlers";
  }
  ZoneTextBuffer buffer(Thread::Current()->zone());
  WriteToBuffer(&buffer, /*base=*/0);
  return buffer.buffer();
}

void SingleTargetCache::set_target(const Code& value) const {
  untag()->set_target(value.ptr());
}

const char* SingleTargetCache::ToCString() const {
  return "SingleTargetCache";
}

SingleTargetCachePtr SingleTargetCache::New() {
  return Object::Allocate<SingleTargetCache>(Heap::kOld);
}

void UnlinkedCall::set_can_patch_to_monomorphic(bool value) const {
  StoreNonPointer(&untag()->can_patch_to_monomorphic_, value);
}

uword UnlinkedCall::Hash() const {
  return String::Handle(target_name()).Hash();
}

bool UnlinkedCall::Equals(const UnlinkedCall& other) const {
  return (target_name() == other.target_name()) &&
         (arguments_descriptor() == other.arguments_descriptor()) &&
         (can_patch_to_monomorphic() == other.can_patch_to_monomorphic());
}

const char* UnlinkedCall::ToCString() const {
  return "UnlinkedCall";
}

UnlinkedCallPtr UnlinkedCall::New() {
  const auto& result =
      UnlinkedCall::Handle(Object::Allocate<UnlinkedCall>(Heap::kOld));
  result.set_can_patch_to_monomorphic(!FLAG_precompiled_mode);
  return result.ptr();
}

MonomorphicSmiableCallPtr MonomorphicSmiableCall::New(classid_t expected_cid,
                                                      const Code& target) {
  const auto& result = MonomorphicSmiableCall::Handle(
      Object::Allocate<MonomorphicSmiableCall>(Heap::kOld));
  result.StoreNonPointer(&result.untag()->expected_cid_, expected_cid);
  result.StoreNonPointer(&result.untag()->entrypoint_, target.EntryPoint());
  return result.ptr();
}

const char* MonomorphicSmiableCall::ToCString() const {
  return "MonomorphicSmiableCall";
}

const char* CallSiteData::ToCString() const {
  // CallSiteData is an abstract class.  We should never reach here.
  UNREACHABLE();
  return "CallSiteData";
}

void CallSiteData::set_target_name(const String& value) const {
  ASSERT(!value.IsNull());
  ASSERT(value.IsCanonical());
  untag()->set_target_name(value.ptr());
}

void CallSiteData::set_arguments_descriptor(const Array& value) const {
  ASSERT(!value.IsNull());
  untag()->set_args_descriptor(value.ptr());
}

#if !defined(DART_PRECOMPILED_RUNTIME)
void ICData::SetReceiversStaticType(const AbstractType& type) const {
  untag()->set_receivers_static_type(type.ptr());

  if (!type.IsNull() && type.HasTypeClass() && (NumArgsTested() == 1) &&
      type.IsInstantiated() && !type.IsFutureOrType()) {
    const Class& cls = Class::Handle(type.type_class());
    if (cls.IsGeneric()) {
      set_tracking_exactness(true);
    }
  }
}
#endif

void ICData::SetTargetAtPos(const Array& data,
                            intptr_t data_pos,
                            intptr_t num_args_tested,
                            const Function& target) {
#if !defined(DART_PRECOMPILED_RUNTIME)
  // JIT
  data.SetAt(data_pos + TargetIndexFor(num_args_tested), target);
#else
  // AOT
  ASSERT(target.HasCode());
  const Code& code = Code::Handle(target.CurrentCode());
  data.SetAt(data_pos + CodeIndexFor(num_args_tested), code);
  data.SetAt(data_pos + EntryPointIndexFor(num_args_tested), target);
#endif
}

uword ICData::Hash() const {
  return String::HashRawSymbol(target_name()) ^ deopt_id();
}

const char* ICData::ToCString() const {
  Zone* zone = Thread::Current()->zone();
  const String& name = String::Handle(zone, target_name());
  return zone->PrintToString("ICData(%s num-args: %" Pd " num-checks: %" Pd
                             " type-args-len: %" Pd ", deopt-id: %" Pd ")",
                             name.ToCString(), NumArgsTested(),
                             NumberOfChecks(), TypeArgsLen(), deopt_id());
}

FunctionPtr ICData::Owner() const {
  Object& obj = Object::Handle(untag()->owner());
  if (obj.IsNull()) {
    ASSERT(Dart::vm_snapshot_kind() == Snapshot::kFullAOT);
    return Function::null();
  } else if (obj.IsFunction()) {
    return Function::Cast(obj).ptr();
  } else {
    ICData& original = ICData::Handle();
    original ^= obj.ptr();
    return original.Owner();
  }
}

ICDataPtr ICData::Original() const {
  if (IsNull()) {
    return ICData::null();
  }
  if (untag()->owner()->IsICData()) {
    return static_cast<ICDataPtr>(untag()->owner());
  }
  return this->ptr();
}

void ICData::SetOriginal(const ICData& value) const {
  ASSERT(value.IsOriginal());
  ASSERT(!value.IsNull());
  untag()->set_owner(static_cast<ObjectPtr>(value.ptr()));
}

void ICData::set_owner(const Function& value) const {
  untag()->set_owner(static_cast<ObjectPtr>(value.ptr()));
}

void ICData::set_deopt_id(intptr_t value) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  ASSERT(value <= kMaxInt32);
  StoreNonPointer(&untag()->deopt_id_, value);
#endif
}

void ICData::set_entries(const Array& value) const {
  ASSERT(!value.IsNull());
  untag()->set_entries<std::memory_order_release>(value.ptr());
}

intptr_t ICData::NumArgsTested() const {
  return untag()->state_bits_.Read<NumArgsTestedBits>();
}

void ICData::SetNumArgsTested(intptr_t value) const {
  ASSERT(Utils::IsUint(2, value));
  untag()->state_bits_.Update<NumArgsTestedBits>(value);
}

intptr_t CallSiteData::TypeArgsLen() const {
  ArgumentsDescriptor args_desc(Array::Handle(arguments_descriptor()));
  return args_desc.TypeArgsLen();
}

intptr_t CallSiteData::CountWithTypeArgs() const {
  ArgumentsDescriptor args_desc(Array::Handle(arguments_descriptor()));
  return args_desc.CountWithTypeArgs();
}

intptr_t CallSiteData::CountWithoutTypeArgs() const {
  ArgumentsDescriptor args_desc(Array::Handle(arguments_descriptor()));
  return args_desc.Count();
}

intptr_t CallSiteData::SizeWithoutTypeArgs() const {
  ArgumentsDescriptor args_desc(Array::Handle(arguments_descriptor()));
  return args_desc.Size();
}

intptr_t CallSiteData::SizeWithTypeArgs() const {
  ArgumentsDescriptor args_desc(Array::Handle(arguments_descriptor()));
  return args_desc.SizeWithTypeArgs();
}

uint32_t ICData::DeoptReasons() const {
  return untag()->state_bits_.Read<DeoptReasonBits>();
}

void ICData::SetDeoptReasons(uint32_t reasons) const {
  untag()->state_bits_.Update<DeoptReasonBits>(reasons);
}

bool ICData::HasDeoptReason(DeoptReasonId reason) const {
  ASSERT(reason <= kLastRecordedDeoptReason);
  return (DeoptReasons() & (1 << reason)) != 0;
}

void ICData::AddDeoptReason(DeoptReasonId reason) const {
  if (reason <= kLastRecordedDeoptReason) {
    untag()->state_bits_.FetchOr<DeoptReasonBits>(1 << reason);
  }
}

const char* ICData::RebindRuleToCString(RebindRule r) {
  switch (r) {
#define RULE_CASE(Name)                                                        \
  case RebindRule::k##Name:                                                    \
    return #Name;
    FOR_EACH_REBIND_RULE(RULE_CASE)
#undef RULE_CASE
    default:
      return nullptr;
  }
}

bool ICData::ParseRebindRule(const char* str, RebindRule* out) {
#define RULE_CASE(Name)                                                        \
  if (strcmp(str, #Name) == 0) {                                               \
    *out = RebindRule::k##Name;                                                \
    return true;                                                               \
  }
  FOR_EACH_REBIND_RULE(RULE_CASE)
#undef RULE_CASE
  return false;
}

ICData::RebindRule ICData::rebind_rule() const {
  return RebindRule(untag()->state_bits_.Read<RebindRuleBits>());
}

void ICData::set_rebind_rule(uint32_t rebind_rule) const {
  untag()->state_bits_.Update<ICData::RebindRuleBits>(rebind_rule);
}

bool ICData::is_static_call() const {
  return rebind_rule() != kInstance;
}

void ICData::clear_state_bits() const {
  untag()->state_bits_ = 0;
}

intptr_t ICData::TestEntryLengthFor(intptr_t num_args,
                                    bool tracking_exactness) {
  return num_args + 1 /* target function*/ + 1 /* frequency */ +
         (tracking_exactness ? 1 : 0) /* exactness state */;
}

intptr_t ICData::TestEntryLength() const {
  return TestEntryLengthFor(NumArgsTested(), is_tracking_exactness());
}

intptr_t ICData::Length() const {
  return (Smi::Value(entries()->untag()->length()) / TestEntryLength());
}

intptr_t ICData::NumberOfChecks() const {
  DEBUG_ONLY(AssertInvariantsAreSatisfied());
  return Length() - 1;
}

bool ICData::NumberOfChecksIs(intptr_t n) const {
  DEBUG_ONLY(AssertInvariantsAreSatisfied());
  return NumberOfChecks() == n;
}

#if defined(DEBUG)
void ICData::AssertInvariantsAreSatisfied() const {
  // See layout and invariant of [ICData] in class comment in object.h.
  //
  // This method can be called without holding any locks, it will grab a
  // snapshot of `entries()` and do it's verification logic on that.
  auto zone = Thread::Current()->zone();
  const auto& array = Array::Handle(zone, entries());

  const intptr_t entry_length = TestEntryLength();
  const intptr_t num_checks = array.Length() / entry_length - 1;
  const intptr_t num_args = NumArgsTested();

  /// Backing store must be multiple of entry length.
  ASSERT((array.Length() % entry_length) == 0);

  /// Entries must be valid.
  for (intptr_t i = 0; i < num_checks; ++i) {
    // Should be valid entry.
    const intptr_t start = entry_length * i;
    for (intptr_t i = 0; i < num_args; ++i) {
      ASSERT(!array.At(start + i)->IsHeapObject());
      ASSERT(array.At(start + i) != smi_illegal_cid().ptr());
    }
    ASSERT(array.At(start + TargetIndexFor(num_args))->IsHeapObject());
    if (is_tracking_exactness()) {
      ASSERT(!array.At(start + ExactnessIndexFor(num_args))->IsHeapObject());
    }
  }

  /// Sentinel at end must be valid.
  const intptr_t sentinel_start = num_checks * entry_length;
  for (intptr_t i = 0; i < entry_length - 1; ++i) {
    ASSERT(array.At(sentinel_start + i) == smi_illegal_cid().ptr());
  }
  if (num_checks == 0) {
    ASSERT(array.At(sentinel_start + entry_length - 1) ==
           smi_illegal_cid().ptr());
    ASSERT(ICData::CachedEmptyICDataArray(num_args, is_tracking_exactness()) ==
           array.ptr());
  } else {
    ASSERT(array.At(sentinel_start + entry_length - 1) == ptr());
  }

  // Invariants for ICData of static calls.
  if (num_args == 0) {
    ASSERT(Length() == 2);
    ASSERT(TestEntryLength() == 2);
  }
}
#endif  // defined(DEBUG)

// Discounts any checks with usage of zero.
intptr_t ICData::NumberOfUsedChecks() const {
  const intptr_t n = NumberOfChecks();
  intptr_t count = 0;
  for (intptr_t i = 0; i < n; i++) {
    if (GetCountAt(i) > 0) {
      count++;
    }
  }
  return count;
}

void ICData::WriteSentinel(const Array& data,
                           intptr_t test_entry_length,
                           const Object& back_ref) {
  ASSERT(!data.IsNull());
  RELEASE_ASSERT(smi_illegal_cid().Value() == kIllegalCid);
  const intptr_t entry_start = data.Length() - test_entry_length;
  for (intptr_t i = 0; i < test_entry_length - 1; i++) {
    data.SetAt(entry_start + i, smi_illegal_cid());
  }
  data.SetAt(entry_start + test_entry_length - 1, back_ref);
}

#if defined(DEBUG)
// Used in asserts to verify that a check is not added twice.
bool ICData::HasCheck(const GrowableArray<intptr_t>& cids) const {
  return FindCheck(cids) != -1;
}
#endif  // DEBUG

intptr_t ICData::FindCheck(const GrowableArray<intptr_t>& cids) const {
  const intptr_t len = NumberOfChecks();
  GrowableArray<intptr_t> class_ids;
  for (intptr_t i = 0; i < len; i++) {
    GetClassIdsAt(i, &class_ids);
    bool matches = true;
    for (intptr_t k = 0; k < class_ids.length(); k++) {
      ASSERT(class_ids[k] != kIllegalCid);
      if (class_ids[k] != cids[k]) {
        matches = false;
        break;
      }
    }
    if (matches) {
      return i;
    }
  }
  return -1;
}

void ICData::TruncateTo(intptr_t num_checks,
                        const CallSiteResetter& proof_of_reload) const {
  USE(proof_of_reload);  // This method can only be called during reload.

  DEBUG_ONLY(AssertInvariantsAreSatisfied());
  ASSERT(num_checks <= NumberOfChecks());

  // Nothing to do.
  if (NumberOfChecks() == num_checks) return;

  auto thread = Thread::Current();
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  auto& array = thread->ArrayHandle();

  // If we make the ICData empty, use the pre-allocated shared backing stores.
  const intptr_t num_args = NumArgsTested();
  if (num_checks == 0) {
    array = ICData::CachedEmptyICDataArray(num_args, is_tracking_exactness());
    set_entries(array);
    return;
  }

  // Otherwise truncate array and initialize sentinel.
  // Use kSmiCid for all slots in the entry except the last, which is a backref
  // to ICData.
  const intptr_t entry_length = TestEntryLength();
  array = entries();
  array.Truncate((num_checks + 1) * entry_length);
  WriteSentinel(array, entry_length, *this);
}

void ICData::ClearCountAt(intptr_t index,
                          const CallSiteResetter& proof_of_reload) const {
  USE(proof_of_reload);  // This method can only be called during reload.

  ASSERT(index >= 0);
  ASSERT(index < NumberOfChecks());
  SetCountAt(index, 0);
}

void ICData::ClearAndSetStaticTarget(
    const Function& func,
    const CallSiteResetter& proof_of_reload) const {
  USE(proof_of_reload);  // This method can only be called during reload.

  // The final entry is always the sentinel.
  DEBUG_ONLY(AssertInvariantsAreSatisfied());

  if (IsImmutable()) return;
  if (NumberOfChecks() == 0) return;

  // Leave one entry.
  TruncateTo(/*num_checks=*/1, proof_of_reload);

  // Reinitialize the one and only entry.
  const intptr_t num_args = NumArgsTested();
  Thread* thread = Thread::Current();
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  Array& data = thread->ArrayHandle();
  data = entries();
  const Smi& object_cid = Smi::Handle(Smi::New(kObjectCid));
  for (intptr_t i = 0; i < num_args; i++) {
    data.SetAt(i, object_cid);
  }
  data.SetAt(TargetIndexFor(num_args), func);
  data.SetAt(CountIndexFor(num_args), Object::smi_zero());
}

bool ICData::ValidateInterceptor(const Function& target) const {
#if !defined(DART_PRECOMPILED_RUNTIME)
  const String& name = String::Handle(target_name());
  if (Function::IsDynamicInvocationForwarderName(name)) {
    return Function::DemangleDynamicInvocationForwarderName(name) ==
           target.name();
  }
#endif
  ObjectStore* store = IsolateGroup::Current()->object_store();
  ASSERT((target.ptr() == store->simple_instance_of_true_function()) ||
         (target.ptr() == store->simple_instance_of_false_function()));
  const String& instance_of_name = String::Handle(
      Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()).ptr());
  ASSERT(target_name() == instance_of_name.ptr());
  return true;
}

void ICData::EnsureHasCheck(const GrowableArray<intptr_t>& class_ids,
                            const Function& target,
                            intptr_t count) const {
  SafepointMutexLocker ml(IsolateGroup::Current()->type_feedback_mutex());

  if (FindCheck(class_ids) != -1) return;
  AddCheckInternal(class_ids, target, count);
}

void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids,
                      const Function& target,
                      intptr_t count) const {
  SafepointMutexLocker ml(IsolateGroup::Current()->type_feedback_mutex());
  AddCheckInternal(class_ids, target, count);
}

void ICData::AddCheckInternal(const GrowableArray<intptr_t>& class_ids,
                              const Function& target,
                              intptr_t count) const {
  ASSERT(
      IsolateGroup::Current()->type_feedback_mutex()->IsOwnedByCurrentThread());

  ASSERT(!is_tracking_exactness());
  ASSERT(!target.IsNull());
  ASSERT((target.name() == target_name()) || ValidateInterceptor(target));
  DEBUG_ASSERT(!HasCheck(class_ids));
  ASSERT(NumArgsTested() > 1);  // Otherwise use 'AddReceiverCheck'.
  const intptr_t num_args_tested = NumArgsTested();
  ASSERT(class_ids.length() == num_args_tested);
  const intptr_t old_num = NumberOfChecks();
  Array& data = Array::Handle(entries());

  // ICData of static calls with NumArgsTested() > 0 have initially a
  // dummy set of cids entered (see ICData::NewForStaticCall). That entry is
  // overwritten by first real type feedback data.
  if (old_num == 1 && num_args_tested == 2) {
    const bool has_dummy_entry =
        Smi::Value(Smi::RawCast(data.At(0))) == kObjectCid &&
        Smi::Value(Smi::RawCast(data.At(1))) == kObjectCid;
    if (has_dummy_entry) {
      ASSERT(target.ptr() == data.At(TargetIndexFor(num_args_tested)));
      // Replace dummy entry.
      Smi& value = Smi::Handle();
      for (intptr_t i = 0; i < NumArgsTested(); i++) {
        ASSERT(class_ids[i] != kIllegalCid);
        value = Smi::New(class_ids[i]);
        data.SetAt(i, value);
      }
      return;
    }
  }
  intptr_t index = -1;
  data = Grow(&index);
  ASSERT(!data.IsNull());
  intptr_t data_pos = index * TestEntryLength();
  Smi& value = Smi::Handle();
  for (intptr_t i = 0; i < class_ids.length(); i++) {
    // kIllegalCid is used as terminating value, do not add it.
    ASSERT(class_ids[i] != kIllegalCid);
    value = Smi::New(class_ids[i]);
    data.SetAt(data_pos + i, value);
  }
  ASSERT(!target.IsNull());
  data.SetAt(data_pos + TargetIndexFor(num_args_tested), target);
  value = Smi::New(count);
  data.SetAt(data_pos + CountIndexFor(num_args_tested), value);
  // Multithreaded access to ICData requires setting of array to be the last
  // operation.
  set_entries(data);
}

ArrayPtr ICData::Grow(intptr_t* index) const {
  DEBUG_ONLY(AssertInvariantsAreSatisfied());

  *index = NumberOfChecks();
  Array& data = Array::Handle(entries());
  const intptr_t new_len = data.Length() + TestEntryLength();
  data = Array::Grow(data, new_len, Heap::kOld);
  WriteSentinel(data, TestEntryLength(), *this);
  return data.ptr();
}

void ICData::DebugDump() const {
  const Function& owner = Function::Handle(Owner());
  THR_Print("ICData::DebugDump\n");
  THR_Print("Owner = %s [deopt=%" Pd "]\n", owner.ToCString(), deopt_id());
  THR_Print("NumArgsTested = %" Pd "\n", NumArgsTested());
  THR_Print("Length = %" Pd "\n", Length());
  THR_Print("NumberOfChecks = %" Pd "\n", NumberOfChecks());

  GrowableArray<intptr_t> class_ids;
  for (intptr_t i = 0; i < NumberOfChecks(); i++) {
    THR_Print("Check[%" Pd "]:", i);
    GetClassIdsAt(i, &class_ids);
    for (intptr_t c = 0; c < class_ids.length(); c++) {
      THR_Print(" %" Pd "", class_ids[c]);
    }
    THR_Print("--- %" Pd " hits\n", GetCountAt(i));
  }
}

void ICData::EnsureHasReceiverCheck(intptr_t receiver_class_id,
                                    const Function& target,
                                    intptr_t count,
                                    StaticTypeExactnessState exactness) const {
  SafepointMutexLocker ml(IsolateGroup::Current()->type_feedback_mutex());

  GrowableArray<intptr_t> class_ids(1);
  class_ids.Add(receiver_class_id);
  if (FindCheck(class_ids) != -1) return;

  AddReceiverCheckInternal(receiver_class_id, target, count, exactness);
}

void ICData::AddReceiverCheck(intptr_t receiver_class_id,
                              const Function& target,
                              intptr_t count,
                              StaticTypeExactnessState exactness) const {
  SafepointMutexLocker ml(IsolateGroup::Current()->type_feedback_mutex());
  AddReceiverCheckInternal(receiver_class_id, target, count, exactness);
}

void ICData::AddReceiverCheckInternal(
    intptr_t receiver_class_id,
    const Function& target,
    intptr_t count,
    StaticTypeExactnessState exactness) const {
#if defined(DEBUG)
  GrowableArray<intptr_t> class_ids(1);
  class_ids.Add(receiver_class_id);
  ASSERT(!HasCheck(class_ids));
#endif  // DEBUG
  ASSERT(!target.IsNull());
  const intptr_t kNumArgsTested = 1;
  ASSERT(NumArgsTested() == kNumArgsTested);  // Otherwise use 'AddCheck'.
  ASSERT(receiver_class_id != kIllegalCid);

  intptr_t index = -1;
  Array& data = Array::Handle(Grow(&index));
  intptr_t data_pos = index * TestEntryLength();
  if ((receiver_class_id == kSmiCid) && (data_pos > 0)) {
    ASSERT(GetReceiverClassIdAt(0) != kSmiCid);
    // Move class occupying position 0 to the data_pos.
    for (intptr_t i = 0; i < TestEntryLength(); i++) {
      data.SetAt(data_pos + i, Object::Handle(data.At(i)));
    }
    // Insert kSmiCid in position 0.
    data_pos = 0;
  }
  data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id)));
  SetTargetAtPos(data, data_pos, kNumArgsTested, target);

#if !defined(DART_PRECOMPILED_RUNTIME)
  data.SetAt(data_pos + CountIndexFor(kNumArgsTested),
             Smi::Handle(Smi::New(count)));
  if (is_tracking_exactness()) {
    data.SetAt(data_pos + ExactnessIndexFor(kNumArgsTested),
               Smi::Handle(Smi::New(exactness.Encode())));
  }
#endif

  // Multithreaded access to ICData requires setting of array to be the last
  // operation.
  set_entries(data);
}

StaticTypeExactnessState ICData::GetExactnessAt(intptr_t index) const {
  if (!is_tracking_exactness()) {
    return StaticTypeExactnessState::NotTracking();
  }
  Thread* thread = Thread::Current();
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  Array& data = thread->ArrayHandle();
  data = entries();
  intptr_t data_pos =
      index * TestEntryLength() + ExactnessIndexFor(NumArgsTested());
  return StaticTypeExactnessState::Decode(
      Smi::Value(Smi::RawCast(data.At(data_pos))));
}

void ICData::GetCheckAt(intptr_t index,
                        GrowableArray<intptr_t>* class_ids,
                        Function* target) const {
  ASSERT(index < NumberOfChecks());
  ASSERT(class_ids != nullptr);
  ASSERT(target != nullptr);
  class_ids->Clear();
  Thread* thread = Thread::Current();
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  Array& data = thread->ArrayHandle();
  data = entries();
  intptr_t data_pos = index * TestEntryLength();
  for (intptr_t i = 0; i < NumArgsTested(); i++) {
    class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos + i))));
  }
  (*target) ^= data.At(data_pos + TargetIndexFor(NumArgsTested()));
}

void ICData::GetClassIdsAt(intptr_t index,
                           GrowableArray<intptr_t>* class_ids) const {
  ASSERT(index < Length());
  ASSERT(class_ids != nullptr);
  ASSERT(IsValidEntryIndex(index));
  class_ids->Clear();
  Thread* thread = Thread::Current();
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  Array& data = thread->ArrayHandle();
  data = entries();
  intptr_t data_pos = index * TestEntryLength();
  for (intptr_t i = 0; i < NumArgsTested(); i++) {
    class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++))));
  }
}

void ICData::GetOneClassCheckAt(intptr_t index,
                                intptr_t* class_id,
                                Function* target) const {
  ASSERT(class_id != nullptr);
  ASSERT(target != nullptr);
  ASSERT(NumArgsTested() == 1);
  Thread* thread = Thread::Current();
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  Array& data = thread->ArrayHandle();
  data = entries();
  const intptr_t data_pos = index * TestEntryLength();
  *class_id = Smi::Value(Smi::RawCast(data.At(data_pos)));
  *target ^= data.At(data_pos + TargetIndexFor(NumArgsTested()));
}

intptr_t ICData::GetCidAt(intptr_t index) const {
  ASSERT(NumArgsTested() == 1);
  Thread* thread = Thread::Current();
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  Array& data = thread->ArrayHandle();
  data = entries();
  const intptr_t data_pos = index * TestEntryLength();
  return Smi::Value(Smi::RawCast(data.At(data_pos)));
}

intptr_t ICData::GetClassIdAt(intptr_t index, intptr_t arg_nr) const {
  GrowableArray<intptr_t> class_ids;
  GetClassIdsAt(index, &class_ids);
  return class_ids[arg_nr];
}

intptr_t ICData::GetReceiverClassIdAt(intptr_t index) const {
  ASSERT(index < Length());
  ASSERT(IsValidEntryIndex(index));
  const intptr_t data_pos = index * TestEntryLength();
  NoSafepointScope no_safepoint;
  ArrayPtr raw_data = entries();
  return Smi::Value(Smi::RawCast(raw_data->untag()->element(data_pos)));
}

FunctionPtr ICData::GetTargetAt(intptr_t index) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
  return nullptr;
#else
  const intptr_t data_pos =
      index * TestEntryLength() + TargetIndexFor(NumArgsTested());
  ASSERT(Object::Handle(Array::Handle(entries()).At(data_pos)).IsFunction());

  NoSafepointScope no_safepoint;
  ArrayPtr raw_data = entries();
  return static_cast<FunctionPtr>(raw_data->untag()->element(data_pos));
#endif
}

void ICData::IncrementCountAt(intptr_t index, intptr_t value) const {
  ASSERT(0 <= value);
  ASSERT(value <= Smi::kMaxValue);
  SetCountAt(index, Utils::Minimum(GetCountAt(index) + value, Smi::kMaxValue));
}

void ICData::SetCountAt(intptr_t index, intptr_t value) const {
  ASSERT(0 <= value);
  ASSERT(value <= Smi::kMaxValue);

  Thread* thread = Thread::Current();
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  Array& data = thread->ArrayHandle();
  data = entries();
  const intptr_t data_pos =
      index * TestEntryLength() + CountIndexFor(NumArgsTested());
  data.SetAt(data_pos, Smi::Handle(Smi::New(value)));
}

intptr_t ICData::GetCountAt(intptr_t index) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
  return 0;
#else
  Thread* thread = Thread::Current();
  REUSABLE_ARRAY_HANDLESCOPE(thread);
  Array& data = thread->ArrayHandle();
  data = entries();
  const intptr_t data_pos =
      index * TestEntryLength() + CountIndexFor(NumArgsTested());
  intptr_t value = Smi::Value(Smi::RawCast(data.At(data_pos)));
  if (value >= 0) return value;

  // The counter very rarely overflows to a negative value, but if it does, we
  // would rather just reset it to zero.
  SetCountAt(index, 0);
  return 0;
#endif
}

intptr_t ICData::AggregateCount() const {
  if (IsNull()) return 0;
  const intptr_t len = NumberOfChecks();
  intptr_t count = 0;
  for (intptr_t i = 0; i < len; i++) {
    count += GetCountAt(i);
  }
  return count;
}

#if !defined(DART_PRECOMPILED_RUNTIME)
ICDataPtr ICData::AsUnaryClassChecksForArgNr(intptr_t arg_nr) const {
  ASSERT(!IsNull());
  ASSERT(NumArgsTested() > arg_nr);
  if ((arg_nr == 0) && (NumArgsTested() == 1)) {
    // Frequent case.
    return ptr();
  }
  const intptr_t kNumArgsTested = 1;
  ICData& result = ICData::Handle(ICData::NewFrom(*this, kNumArgsTested));
  const intptr_t len = NumberOfChecks();
  for (intptr_t i = 0; i < len; i++) {
    const intptr_t class_id = GetClassIdAt(i, arg_nr);
    const intptr_t count = GetCountAt(i);
    if (count == 0) {
      continue;
    }
    intptr_t duplicate_class_id = -1;
    const intptr_t result_len = result.NumberOfChecks();
    for (intptr_t k = 0; k < result_len; k++) {
      if (class_id == result.GetReceiverClassIdAt(k)) {
        duplicate_class_id = k;
        break;
      }
    }
    if (duplicate_class_id >= 0) {
      // This check is valid only when checking the receiver.
      ASSERT((arg_nr != 0) ||
             (result.GetTargetAt(duplicate_class_id) == GetTargetAt(i)));
      result.IncrementCountAt(duplicate_class_id, count);
    } else {
      // This will make sure that Smi is first if it exists.
      result.AddReceiverCheckInternal(class_id,
                                      Function::Handle(GetTargetAt(i)), count,
                                      StaticTypeExactnessState::NotTracking());
    }
  }

  return result.ptr();
}

// (cid, count) tuple used to sort ICData by count.
struct CidCount {
  CidCount(intptr_t cid_, intptr_t count_, Function* f_)
      : cid(cid_), count(count_), function(f_) {}

  static int HighestCountFirst(const CidCount* a, const CidCount* b);

  intptr_t cid;
  intptr_t count;
  Function* function;
};

int CidCount::HighestCountFirst(const CidCount* a, const CidCount* b) {
  if (a->count > b->count) {
    return -1;
  }
  return (a->count < b->count) ? 1 : 0;
}

ICDataPtr ICData::AsUnaryClassChecksSortedByCount() const {
  ASSERT(!IsNull());
  const intptr_t kNumArgsTested = 1;
  const intptr_t len = NumberOfChecks();
  if (len <= 1) {
    // No sorting needed.
    return AsUnaryClassChecks();
  }
  GrowableArray<CidCount> aggregate;
  for (intptr_t i = 0; i < len; i++) {
    const intptr_t class_id = GetClassIdAt(i, 0);
    const intptr_t count = GetCountAt(i);
    if (count == 0) {
      continue;
    }
    bool found = false;
    for (intptr_t r = 0; r < aggregate.length(); r++) {
      if (aggregate[r].cid == class_id) {
        aggregate[r].count += count;
        found = true;
        break;
      }
    }
    if (!found) {
      aggregate.Add(
          CidCount(class_id, count, &Function::ZoneHandle(GetTargetAt(i))));
    }
  }
  aggregate.Sort(CidCount::HighestCountFirst);

  ICData& result = ICData::Handle(ICData::NewFrom(*this, kNumArgsTested));
  ASSERT(result.NumberOfChecksIs(0));
  // Room for all entries and the sentinel.
  const intptr_t data_len = result.TestEntryLength() * (aggregate.length() + 1);
  // Allocate the array but do not assign it to result until we have populated
  // it with the aggregate data and the terminating sentinel.
  const Array& data = Array::Handle(Array::New(data_len, Heap::kOld));
  intptr_t pos = 0;
  for (intptr_t i = 0; i < aggregate.length(); i++) {
    data.SetAt(pos + 0, Smi::Handle(Smi::New(aggregate[i].cid)));
    data.SetAt(pos + TargetIndexFor(1), *aggregate[i].function);
    data.SetAt(pos + CountIndexFor(1),
               Smi::Handle(Smi::New(aggregate[i].count)));

    pos += result.TestEntryLength();
  }
  WriteSentinel(data, result.TestEntryLength(), result);
  result.set_entries(data);
  ASSERT(result.NumberOfChecksIs(aggregate.length()));
  return result.ptr();
}

UnlinkedCallPtr ICData::AsUnlinkedCall() const {
  ASSERT(NumArgsTested() == 1);
  ASSERT(!is_tracking_exactness());
  const UnlinkedCall& result = UnlinkedCall::Handle(UnlinkedCall::New());
  result.set_target_name(String::Handle(target_name()));
  result.set_arguments_descriptor(Array::Handle(arguments_descriptor()));
  result.set_can_patch_to_monomorphic(!FLAG_precompiled_mode ||
                                      receiver_cannot_be_smi());
  return result.ptr();
}

bool ICData::HasReceiverClassId(intptr_t class_id) const {
  ASSERT(NumArgsTested() > 0);
  const intptr_t len = NumberOfChecks();
  for (intptr_t i = 0; i < len; i++) {
    if (IsUsedAt(i)) {
      const intptr_t test_class_id = GetReceiverClassIdAt(i);
      if (test_class_id == class_id) {
        return true;
      }
    }
  }
  return false;
}
#endif

bool ICData::IsUsedAt(intptr_t i) const {
  if (GetCountAt(i) <= 0) {
    // Do not mistake unoptimized static call ICData for unused.
    // See ICData::AddTarget.
    // TODO(srdjan): Make this test more robust.
    if (NumArgsTested() > 0) {
      const intptr_t cid = GetReceiverClassIdAt(i);
      if (cid == kObjectCid) {
        return true;
      }
    }
    return false;
  }
  return true;
}

void ICData::Init() {
  for (int i = 0; i <= kCachedICDataMaxArgsTestedWithoutExactnessTracking;
       i++) {
    cached_icdata_arrays_
        [kCachedICDataZeroArgTestedWithoutExactnessTrackingIdx + i] =
            ICData::NewNonCachedEmptyICDataArray(i, false);
  }
  cached_icdata_arrays_[kCachedICDataOneArgWithExactnessTrackingIdx] =
      ICData::NewNonCachedEmptyICDataArray(1, true);
}

void ICData::Cleanup() {
  for (int i = 0; i < kCachedICDataArrayCount; ++i) {
    cached_icdata_arrays_[i] = nullptr;
  }
}

ArrayPtr ICData::NewNonCachedEmptyICDataArray(intptr_t num_args_tested,
                                              bool tracking_exactness) {
  // IC data array must be null terminated (sentinel entry).
  const intptr_t len = TestEntryLengthFor(num_args_tested, tracking_exactness);
  const Array& array = Array::Handle(Array::New(len, Heap::kOld));
  // Only empty [ICData]s are allowed to have a non-ICData backref.
  WriteSentinel(array, len, /*back_ref=*/smi_illegal_cid());
  array.MakeImmutable();
  return array.ptr();
}

ArrayPtr ICData::CachedEmptyICDataArray(intptr_t num_args_tested,
                                        bool tracking_exactness) {
  if (tracking_exactness) {
    ASSERT(num_args_tested == 1);
    return cached_icdata_arrays_[kCachedICDataOneArgWithExactnessTrackingIdx];
  } else {
    ASSERT(num_args_tested >= 0);
    ASSERT(num_args_tested <=
           kCachedICDataMaxArgsTestedWithoutExactnessTracking);
    return cached_icdata_arrays_
        [kCachedICDataZeroArgTestedWithoutExactnessTrackingIdx +
         num_args_tested];
  }
}

bool ICData::IsCachedEmptyEntry(const Array& array) {
  for (int i = 0; i < kCachedICDataArrayCount; ++i) {
    if (cached_icdata_arrays_[i] == array.ptr()) return true;
  }
  return false;
}

// Does not initialize ICData array.
ICDataPtr ICData::NewDescriptor(Zone* zone,
                                const Function& owner,
                                const String& target_name,
                                const Array& arguments_descriptor,
                                intptr_t deopt_id,
                                intptr_t num_args_tested,
                                RebindRule rebind_rule,
                                const AbstractType& receivers_static_type) {
#if !defined(DART_PRECOMPILED_RUNTIME)
  // We should only have null owners in the precompiled runtime, if the
  // owning function for a Code object was optimized out.
  ASSERT(!owner.IsNull());
#endif
  ASSERT(!target_name.IsNull());
  ASSERT(!arguments_descriptor.IsNull());
  ASSERT(Object::icdata_class() != Class::null());
  ASSERT(num_args_tested >= 0);
  // IC data objects are long living objects, allocate them in old generation.
  const auto& result =
      ICData::Handle(zone, Object::Allocate<ICData>(Heap::kOld));
  result.set_owner(owner);
  result.set_target_name(target_name);
  result.set_arguments_descriptor(arguments_descriptor);
  NOT_IN_PRECOMPILED(result.set_deopt_id(deopt_id));
  ASSERT_EQUAL(result.untag()->state_bits_, 0);
  result.set_rebind_rule(rebind_rule);
  result.SetNumArgsTested(num_args_tested);
  NOT_IN_PRECOMPILED(result.SetReceiversStaticType(receivers_static_type));
  return result.ptr();
}

bool ICData::IsImmutable() const {
  return entries()->IsImmutableArray();
}

ICDataPtr ICData::New() {
  // IC data objects are long living objects, allocate them in old generation.
  const auto& result = ICData::Handle(Object::Allocate<ICData>(Heap::kOld));
  ASSERT_EQUAL(result.untag()->state_bits_, 0);
  result.set_deopt_id(DeoptId::kNone);
  return result.ptr();
}

ICDataPtr ICData::New(const Function& owner,
                      const String& target_name,
                      const Array& arguments_descriptor,
                      intptr_t deopt_id,
                      intptr_t num_args_tested,
                      RebindRule rebind_rule,
                      const AbstractType& receivers_static_type) {
  Zone* zone = Thread::Current()->zone();
  const ICData& result = ICData::Handle(
      zone,
      NewDescriptor(zone, owner, target_name, arguments_descriptor, deopt_id,
                    num_args_tested, rebind_rule, receivers_static_type));
  result.set_entries(Array::Handle(
      zone,
      CachedEmptyICDataArray(num_args_tested, result.is_tracking_exactness())));
  return result.ptr();
}

ICDataPtr ICData::NewWithCheck(const Function& owner,
                               const String& target_name,
                               const Array& arguments_descriptor,
                               intptr_t deopt_id,
                               intptr_t num_args_tested,
                               RebindRule rebind_rule,
                               GrowableArray<intptr_t>* cids,
                               const Function& target,
                               const AbstractType& receiver_type) {
  ASSERT((cids != nullptr) && !target.IsNull());
  ASSERT(cids->length() == num_args_tested);

  Zone* zone = Thread::Current()->zone();
  const auto& result = ICData::Handle(
      zone,
      NewDescriptor(zone, owner, target_name, arguments_descriptor, deopt_id,
                    num_args_tested, rebind_rule, receiver_type));

  const intptr_t kNumEntries = 2;  // 1 entry and a sentinel.
  const intptr_t entry_len =
      TestEntryLengthFor(num_args_tested, result.is_tracking_exactness());
  const auto& array =
      Array::Handle(zone, Array::New(kNumEntries * entry_len, Heap::kOld));

  auto& cid = Smi::Handle(zone);
  for (intptr_t i = 0; i < num_args_tested; ++i) {
    cid = Smi::New((*cids)[i]);
    array.SetAt(i, cid);
  }

  SetTargetAtPos(array, 0, num_args_tested, target);
#if !defined(DART_PRECOMPILED_RUNTIME)
  array.SetAt(CountIndexFor(num_args_tested), Object::smi_zero());
#endif
  WriteSentinel(array, entry_len, result);

  result.set_entries(array);

  return result.ptr();
}

ICDataPtr ICData::NewForStaticCall(const Function& owner,
                                   const Function& target,
                                   const Array& arguments_descriptor,
                                   intptr_t deopt_id,
                                   intptr_t num_args_tested,
                                   RebindRule rebind_rule) {
  // See `MethodRecognizer::NumArgsCheckedForStaticCall`.
  ASSERT(num_args_tested == 0 || num_args_tested == 2);
  ASSERT(!target.IsNull());

  Zone* zone = Thread::Current()->zone();
  const auto& target_name = String::Handle(zone, target.name());
  GrowableArray<intptr_t> cids(num_args_tested);
  if (num_args_tested == 2) {
    cids.Add(kObjectCid);
    cids.Add(kObjectCid);
  }
  return ICData::NewWithCheck(owner, target_name, arguments_descriptor,
                              deopt_id, num_args_tested, rebind_rule, &cids,
                              target, Object::null_abstract_type());
}

#if !defined(DART_PRECOMPILED_RUNTIME)
ICDataPtr ICData::NewFrom(const ICData& from, intptr_t num_args_tested) {
  // See comment in [ICData::Clone] why we access the megamorphic bit first.
  const bool is_megamorphic = from.is_megamorphic();

  const ICData& result = ICData::Handle(ICData::New(
      Function::Handle(from.Owner()), String::Handle(from.target_name()),
      Array::Handle(from.arguments_descriptor()), from.deopt_id(),
      num_args_tested, from.rebind_rule(),
      AbstractType::Handle(from.receivers_static_type())));
  // Copy deoptimization reasons.
  result.SetDeoptReasons(from.DeoptReasons());
  result.set_is_megamorphic(is_megamorphic);
  return result.ptr();
}

ICDataPtr ICData::Clone(const ICData& from) {
  Zone* zone = Thread::Current()->zone();

  // We have to check the megamorphic bit before accessing the entries of the
  // ICData to ensure all writes to the entries have been flushed and are
  // visible at this point.
  //
  // This will allow us to maintain the invariant that if the megamorphic bit is
  // set, the number of entries in the ICData have reached the limit.
  const bool is_megamorphic = from.is_megamorphic();

  const ICData& result = ICData::Handle(
      zone, ICData::NewDescriptor(
                zone, Function::Handle(zone, from.Owner()),
                String::Handle(zone, from.target_name()),
                Array::Handle(zone, from.arguments_descriptor()),
                from.deopt_id(), from.NumArgsTested(), from.rebind_rule(),
                AbstractType::Handle(zone, from.receivers_static_type())));
  // Clone entry array.
  const Array& from_array = Array::Handle(zone, from.entries());
  if (ICData::IsCachedEmptyEntry(from_array)) {
    result.set_entries(from_array);
  } else {
    const intptr_t len = from_array.Length();
    const Array& cloned_array =
        Array::Handle(zone, Array::New(len, Heap::kOld));
    Object& obj = Object::Handle(zone);
    for (intptr_t i = 0; i < len; i++) {
      obj = from_array.At(i);
      cloned_array.SetAt(i, obj);
    }
    // Update backref in our clone.
    cloned_array.SetAt(cloned_array.Length() - 1, result);
    result.set_entries(cloned_array);
  }
  // Copy deoptimization reasons.
  result.SetDeoptReasons(from.DeoptReasons());
  result.set_is_megamorphic(is_megamorphic);

  DEBUG_ONLY(result.AssertInvariantsAreSatisfied());

  return result.ptr();
}
#endif

ICDataPtr ICData::ICDataOfEntriesArray(const Array& array) {
  const auto& back_ref = Object::Handle(array.At(array.Length() - 1));
  if (back_ref.ptr() == smi_illegal_cid().ptr()) {
    ASSERT(IsCachedEmptyEntry(array));
    return ICData::null();
  }

  const auto& ic_data = ICData::Cast(back_ref);
  DEBUG_ONLY(ic_data.AssertInvariantsAreSatisfied());
  return ic_data.ptr();
}

const char* WeakSerializationReference::ToCString() const {
  return Object::Handle(target()).ToCString();
}

ObjectPtr WeakSerializationReference::New(const Object& target,
                                          const Object& replacement) {
  ASSERT(Object::weak_serialization_reference_class() != Class::null());
  // Don't wrap any object in the VM heap, as all objects in the VM isolate
  // heap are currently serialized.
  //
  // Note that we _do_ wrap Smis if requested. Smis are serialized in the Mint
  // cluster, and so dropping them if not strongly referenced saves space in
  // the snapshot.
  if (target.ptr()->IsHeapObject() && target.InVMIsolateHeap()) {
    return target.ptr();
  }
  // If the target is a WSR that already uses the replacement, then return it.
  if (target.IsWeakSerializationReference() &&
      WeakSerializationReference::Cast(target).replacement() ==
          replacement.ptr()) {
    return target.ptr();
  }
  const auto& result = WeakSerializationReference::Handle(
      Object::Allocate<WeakSerializationReference>(Heap::kOld));
  // Don't nest WSRs, instead just use the old WSR's target.
  result.untag()->set_target(target.IsWeakSerializationReference()
                                 ? WeakSerializationReference::Unwrap(target)
                                 : target.ptr());
  result.untag()->set_replacement(replacement.ptr());
  return result.ptr();
}

const char* WeakArray::ToCString() const {
  return Thread::Current()->zone()->PrintToString("WeakArray len:%" Pd,
                                                  Length());
}

WeakArrayPtr WeakArray::New(intptr_t length, Heap::Space space) {
  ASSERT(Object::weak_array_class() != Class::null());
  if (!IsValidLength(length)) {
    // This should be caught before we reach here.
    FATAL("Fatal error in WeakArray::New: invalid len %" Pd "\n", length);
  }
  auto raw = Object::Allocate<WeakArray>(space, length);
  NoSafepointScope no_safepoint;
  raw->untag()->set_length(Smi::New(length));
  return raw;
}

#if defined(INCLUDE_IL_PRINTER)
Code::Comments& Code::Comments::New(intptr_t count) {
  Comments* comments;
  if (count < 0 || count > (kIntptrMax / kNumberOfEntries)) {
    // This should be caught before we reach here.
    FATAL("Fatal error in Code::Comments::New: invalid count %" Pd "\n", count);
  }
  if (count == 0) {
    comments = new Comments(Object::empty_array());
  } else {
    const Array& data =
        Array::Handle(Array::New(count * kNumberOfEntries, Heap::kOld));
    comments = new Comments(data);
  }
  return *comments;
}

intptr_t Code::Comments::Length() const {
  if (comments_.IsNull()) {
    return 0;
  }
  return comments_.Length() / kNumberOfEntries;
}

intptr_t Code::Comments::PCOffsetAt(intptr_t idx) const {
  return Smi::Value(
      Smi::RawCast(comments_.At(idx * kNumberOfEntries + kPCOffsetEntry)));
}

void Code::Comments::SetPCOffsetAt(intptr_t idx, intptr_t pc) {
  comments_.SetAt(idx * kNumberOfEntries + kPCOffsetEntry,
                  Smi::Handle(Smi::New(pc)));
}

const char* Code::Comments::CommentAt(intptr_t idx) const {
  string_ ^= comments_.At(idx * kNumberOfEntries + kCommentEntry);
  return string_.ToCString();
}

void Code::Comments::SetCommentAt(intptr_t idx, const String& comment) {
  comments_.SetAt(idx * kNumberOfEntries + kCommentEntry, comment);
}

Code::Comments::Comments(const Array& comments)
    : comments_(comments), string_(String::Handle()) {}
#endif  // defined(INCLUDE_IL_PRINTER)

const char* Code::EntryKindToCString(EntryKind kind) {
  switch (kind) {
    case EntryKind::kNormal:
      return "Normal";
    case EntryKind::kUnchecked:
      return "Unchecked";
    case EntryKind::kMonomorphic:
      return "Monomorphic";
    case EntryKind::kMonomorphicUnchecked:
      return "MonomorphicUnchecked";
    default:
      UNREACHABLE();
      return nullptr;
  }
}

bool Code::ParseEntryKind(const char* str, EntryKind* out) {
  if (strcmp(str, "Normal") == 0) {
    *out = EntryKind::kNormal;
    return true;
  } else if (strcmp(str, "Unchecked") == 0) {
    *out = EntryKind::kUnchecked;
    return true;
  } else if (strcmp(str, "Monomorphic") == 0) {
    *out = EntryKind::kMonomorphic;
    return true;
  } else if (strcmp(str, "MonomorphicUnchecked") == 0) {
    *out = EntryKind::kMonomorphicUnchecked;
    return true;
  }
  return false;
}

LocalVarDescriptorsPtr Code::GetLocalVarDescriptors() const {
  const LocalVarDescriptors& v = LocalVarDescriptors::Handle(var_descriptors());
  if (v.IsNull()) {
    ASSERT(!is_optimized());
    const Function& f = Function::Handle(function());
    ASSERT(!f.IsIrregexpFunction());  // Not yet implemented.
    Compiler::ComputeLocalVarDescriptors(*this);
  }
  return var_descriptors();
}

void Code::set_owner(const Object& owner) const {
#if defined(DEBUG)
  const auto& unwrapped_owner =
      Object::Handle(WeakSerializationReference::Unwrap(owner));
  ASSERT(unwrapped_owner.IsFunction() || unwrapped_owner.IsClass() ||
         unwrapped_owner.IsAbstractType());
#endif
  untag()->set_owner(owner.ptr());
}

void Code::set_state_bits(intptr_t bits) const {
  StoreNonPointer(&untag()->state_bits_, bits);
}

void Code::set_is_optimized(bool value) const {
  set_state_bits(OptimizedBit::update(value, untag()->state_bits_));
}

void Code::set_is_force_optimized(bool value) const {
  set_state_bits(ForceOptimizedBit::update(value, untag()->state_bits_));
}

void Code::set_is_alive(bool value) const {
  set_state_bits(AliveBit::update(value, untag()->state_bits_));
}

void Code::set_is_discarded(bool value) const {
  set_state_bits(DiscardedBit::update(value, untag()->state_bits_));
}

void Code::set_compressed_stackmaps(const CompressedStackMaps& maps) const {
  ASSERT(maps.IsOld());
  untag()->set_compressed_stackmaps(maps.ptr());
}

#if !defined(DART_PRECOMPILED_RUNTIME)
intptr_t Code::num_variables() const {
  ASSERT(!FLAG_precompiled_mode);
  return Smi::Value(Smi::RawCast(untag()->catch_entry()));
}
void Code::set_num_variables(intptr_t num_variables) const {
  ASSERT(!FLAG_precompiled_mode);
  untag()->set_catch_entry(Smi::New(num_variables));
}
#endif

TypedDataPtr Code::catch_entry_moves_maps() const {
  return TypedData::RawCast(untag()->catch_entry());
}
void Code::set_catch_entry_moves_maps(const TypedData& maps) const {
  untag()->set_catch_entry(maps.ptr());
}

void Code::set_deopt_info_array(const Array& array) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  ASSERT(array.IsOld());
  untag()->set_deopt_info_array(array.ptr());
#endif
}

void Code::set_static_calls_target_table(const Array& value) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  untag()->set_static_calls_target_table(value.ptr());
#endif
#if defined(DEBUG)
  // Check that the table is sorted by pc offsets.
  // FlowGraphCompiler::AddStaticCallTarget adds pc-offsets to the table while
  // emitting assembly. This guarantees that every succeeding pc-offset is
  // larger than the previously added one.
  StaticCallsTable entries(value);
  const intptr_t count = entries.Length();
  for (intptr_t i = 0; i < count - 1; ++i) {
    auto left = Smi::Value(entries[i].Get<kSCallTableKindAndOffset>());
    auto right = Smi::Value(entries[i + 1].Get<kSCallTableKindAndOffset>());
    ASSERT(OffsetField::decode(left) < OffsetField::decode(right));
  }
#endif  // DEBUG
}

ObjectPoolPtr Code::GetObjectPool() const {
#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
  if (FLAG_precompiled_mode) {
    return IsolateGroup::Current()->object_store()->global_object_pool();
  }
#endif
  return object_pool();
}

bool Code::HasBreakpoint() const {
#if defined(PRODUCT)
  return false;
#else
  return IsolateGroup::Current()->debugger()->HasBreakpointInCode(*this);
#endif
}

TypedDataPtr Code::GetDeoptInfoAtPc(uword pc,
                                    ICData::DeoptReasonId* deopt_reason,
                                    uint32_t* deopt_flags) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  ASSERT(Dart::vm_snapshot_kind() == Snapshot::kFullAOT);
  return TypedData::null();
#else
  ASSERT(is_optimized());
  const Instructions& instrs = Instructions::Handle(instructions());
  uword code_entry = instrs.PayloadStart();
  const Array& table = Array::Handle(deopt_info_array());
  if (table.IsNull()) {
    ASSERT(Dart::vm_snapshot_kind() == Snapshot::kFullAOT);
    return TypedData::null();
  }
  // Linear search for the PC offset matching the target PC.
  intptr_t length = DeoptTable::GetLength(table);
  Smi& offset = Smi::Handle();
  Smi& reason_and_flags = Smi::Handle();
  TypedData& info = TypedData::Handle();
  for (intptr_t i = 0; i < length; ++i) {
    DeoptTable::GetEntry(table, i, &offset, &info, &reason_and_flags);
    if (pc == (code_entry + offset.Value())) {
      ASSERT(!info.IsNull());
      *deopt_reason = DeoptTable::ReasonField::decode(reason_and_flags.Value());
      *deopt_flags = DeoptTable::FlagsField::decode(reason_and_flags.Value());
      return info.ptr();
    }
  }
  *deopt_reason = ICData::kDeoptUnknown;
  return TypedData::null();
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

intptr_t Code::BinarySearchInSCallTable(uword pc) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  NoSafepointScope no_safepoint;
  const Array& table = Array::Handle(untag()->static_calls_target_table());
  StaticCallsTable entries(table);
  const intptr_t pc_offset = pc - PayloadStart();
  intptr_t imin = 0;
  intptr_t imax = (table.Length() / kSCallTableEntryLength) - 1;
  while (imax >= imin) {
    const intptr_t imid = imin + (imax - imin) / 2;
    const auto offset = OffsetField::decode(
        Smi::Value(entries[imid].Get<kSCallTableKindAndOffset>()));
    if (offset < pc_offset) {
      imin = imid + 1;
    } else if (offset > pc_offset) {
      imax = imid - 1;
    } else {
      return imid;
    }
  }
#endif
  return -1;
}

FunctionPtr Code::GetStaticCallTargetFunctionAt(uword pc) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
  return Function::null();
#else
  const intptr_t i = BinarySearchInSCallTable(pc);
  if (i < 0) {
    return Function::null();
  }
  const Array& array = Array::Handle(untag()->static_calls_target_table());
  StaticCallsTable entries(array);
  return entries[i].Get<kSCallTableFunctionTarget>();
#endif
}

void Code::SetStaticCallTargetCodeAt(uword pc, const Code& code) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  const intptr_t i = BinarySearchInSCallTable(pc);
  ASSERT(i >= 0);
  const Array& array = Array::Handle(untag()->static_calls_target_table());
  StaticCallsTable entries(array);
  ASSERT(code.IsNull() ||
         (code.function() == entries[i].Get<kSCallTableFunctionTarget>()));
  return entries[i].Set<kSCallTableCodeOrTypeTarget>(code);
#endif
}

void Code::SetStubCallTargetCodeAt(uword pc, const Code& code) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  const intptr_t i = BinarySearchInSCallTable(pc);
  ASSERT(i >= 0);
  const Array& array = Array::Handle(untag()->static_calls_target_table());
  StaticCallsTable entries(array);
#if defined(DEBUG)
  if (entries[i].Get<kSCallTableFunctionTarget>() == Function::null()) {
    ASSERT(!code.IsNull() && Object::Handle(code.owner()).IsClass());
  } else {
    ASSERT(code.IsNull() ||
           (code.function() == entries[i].Get<kSCallTableFunctionTarget>()));
  }
#endif
  return entries[i].Set<kSCallTableCodeOrTypeTarget>(code);
#endif
}

void Code::Disassemble(DisassemblyFormatter* formatter) const {
#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
  if (!FLAG_support_disassembler) {
    return;
  }
  const uword start = PayloadStart();
  if (formatter == nullptr) {
    Disassembler::Disassemble(start, start + Size(), *this);
  } else {
    Disassembler::Disassemble(start, start + Size(), formatter, *this);
  }
#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
}

#if defined(INCLUDE_IL_PRINTER)
#if defined(PRODUCT)
// In PRODUCT builds we don't have space in Code object to store code comments
// so we move them into malloced heap (and leak them). This functionality
// is only intended to be used in AOT compiler so leaking is fine.
class MallocCodeComments final : public CodeComments {
 public:
  explicit MallocCodeComments(const CodeComments& comments)
      : length_(comments.Length()), comments_(new Comment[comments.Length()]) {
    for (intptr_t i = 0; i < length_; i++) {
      comments_[i].pc_offset = comments.PCOffsetAt(i);
      comments_[i].comment =
          CStringUniquePtr(Utils::StrDup(comments.CommentAt(i)));
    }
  }

  intptr_t Length() const override { return length_; }

  intptr_t PCOffsetAt(intptr_t i) const override {
    return comments_[i].pc_offset;
  }

  const char* CommentAt(intptr_t i) const override {
    return comments_[i].comment.get();
  }

 private:
  struct Comment {
    intptr_t pc_offset;
    CStringUniquePtr comment;
  };

  intptr_t length_;
  std::unique_ptr<Comment[]> comments_;
};
#endif

const CodeComments& Code::comments() const {
#if defined(PRODUCT)
  auto comments =
      static_cast<CodeComments*>(Thread::Current()->heap()->GetPeer(ptr()));
  return (comments != nullptr) ? *comments : Code::Comments::New(0);
#else
  return *new Code::Comments(Array::Handle(untag()->comments()));
#endif
}

void Code::set_comments(const CodeComments& comments) const {
#if !defined(PRODUCT)
  auto& wrapper = static_cast<const Code::Comments&>(comments);
  ASSERT(wrapper.comments_.IsOld());
  untag()->set_comments(wrapper.comments_.ptr());
#else
  if (FLAG_code_comments && comments.Length() > 0) {
    Thread::Current()->heap()->SetPeer(ptr(), new MallocCodeComments(comments));
  } else {
    Thread::Current()->heap()->SetPeer(ptr(), nullptr);
  }
#endif
}
#endif  // defined(INCLUDE_IL_PRINTER)

void Code::SetPrologueOffset(intptr_t offset) const {
#if defined(PRODUCT)
  UNREACHABLE();
#else
  ASSERT(offset >= 0);
  untag()->set_return_address_metadata(Smi::New(offset));
#endif
}

intptr_t Code::GetPrologueOffset() const {
#if defined(PRODUCT)
  UNREACHABLE();
  return -1;
#else
  const Object& object = Object::Handle(untag()->return_address_metadata());
  // In the future we may put something other than a smi in
  // |return_address_metadata_|.
  if (object.IsNull() || !object.IsSmi()) {
    return -1;
  }
  return Smi::Cast(object).Value();
#endif
}

ArrayPtr Code::inlined_id_to_function() const {
  return untag()->inlined_id_to_function();
}

void Code::set_inlined_id_to_function(const Array& value) const {
  ASSERT(value.IsOld());
  untag()->set_inlined_id_to_function(value.ptr());
}

CodePtr Code::New(intptr_t pointer_offsets_length) {
  if (pointer_offsets_length < 0 || pointer_offsets_length > kMaxElements) {
    // This should be caught before we reach here.
    FATAL("Fatal error in Code::New: invalid pointer_offsets_length %" Pd "\n",
          pointer_offsets_length);
  }
  ASSERT(Object::code_class() != Class::null());
  Code& result = Code::Handle();
  {
    auto raw = Object::Allocate<Code>(Heap::kOld, pointer_offsets_length);
    NoSafepointScope no_safepoint;
    result = raw;
    ASSERT_EQUAL(result.untag()->state_bits_, 0);
    result.set_pointer_offsets_length(pointer_offsets_length);
  }
  DEBUG_ASSERT(result.compile_timestamp() == 0);
#if defined(INCLUDE_IL_PRINTER)
  result.set_comments(Comments::New(0));
#endif
  result.set_pc_descriptors(Object::empty_descriptors());
  result.set_compressed_stackmaps(Object::empty_compressed_stackmaps());
  return result.ptr();
}

#if !defined(DART_PRECOMPILED_RUNTIME)
CodePtr Code::FinalizeCodeAndNotify(const Function& function,
                                    FlowGraphCompiler* compiler,
                                    compiler::Assembler* assembler,
                                    PoolAttachment pool_attachment,
                                    bool optimized,
                                    CodeStatistics* stats) {
  auto thread = Thread::Current();
  ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());

  const auto& code = Code::Handle(
      FinalizeCode(compiler, assembler, pool_attachment, optimized, stats));
  NotifyCodeObservers(function, code, optimized);
  return code.ptr();
}

CodePtr Code::FinalizeCodeAndNotify(const char* name,
                                    FlowGraphCompiler* compiler,
                                    compiler::Assembler* assembler,
                                    PoolAttachment pool_attachment,
                                    bool optimized,
                                    CodeStatistics* stats) {
  auto thread = Thread::Current();
  ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());

  const auto& code = Code::Handle(
      FinalizeCode(compiler, assembler, pool_attachment, optimized, stats));
  NotifyCodeObservers(name, code, optimized);
  return code.ptr();
}

#if defined(DART_PRECOMPILER)
DECLARE_FLAG(charp, write_v8_snapshot_profile_to);
DECLARE_FLAG(charp, trace_precompiler_to);
#endif  // defined(DART_PRECOMPILER)

CodePtr Code::FinalizeCode(FlowGraphCompiler* compiler,
                           compiler::Assembler* assembler,
                           PoolAttachment pool_attachment,
                           bool optimized,
                           CodeStatistics* stats /* = nullptr */) {
  auto thread = Thread::Current();
  ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());

  ASSERT(assembler != nullptr);
  ObjectPool& object_pool = ObjectPool::Handle();

  if (pool_attachment == PoolAttachment::kAttachPool) {
    if (assembler->HasObjectPoolBuilder()) {
      object_pool =
          ObjectPool::NewFromBuilder(assembler->object_pool_builder());
    } else {
      object_pool = ObjectPool::empty_object_pool().ptr();
    }
  } else {
#if defined(DART_PRECOMPILER)
    if (assembler->HasObjectPoolBuilder() &&
        assembler->object_pool_builder().HasParent()) {
      // We are not going to write this pool into snapshot, but we will use
      // it to emit references from this code object to other objects in the
      // snapshot that it uses.
      object_pool =
          ObjectPool::NewFromBuilder(assembler->object_pool_builder());
    }
#endif  // defined(DART_PRECOMPILER)
  }

  // Allocate the Code and Instructions objects.  Code is allocated first
  // because a GC during allocation of the code will leave the instruction
  // pages read-only.
  intptr_t pointer_offset_count = assembler->CountPointerOffsets();
  Code& code = Code::ZoneHandle(Code::New(pointer_offset_count));
#ifdef TARGET_ARCH_IA32
  assembler->GetSelfHandle() = code.ptr();
#endif
  Instructions& instrs = Instructions::ZoneHandle(Instructions::New(
      assembler->CodeSize(), assembler->has_monomorphic_entry(),
      assembler->should_be_aligned()));

  {
    // Important: if GC is triggered at any point between Instructions::New
    // and here it would write protect instructions object that we are trying
    // to fill in.
    NoSafepointScope no_safepoint;

    // Copy the instructions into the instruction area and apply all fixups.
    // Embedded pointers are still in handles at this point.
    MemoryRegion region(reinterpret_cast<void*>(
                            Instructions::WritablePayloadStart(instrs.ptr())),
                        instrs.Size());
    assembler->FinalizeInstructions(region);

    const auto& pointer_offsets = assembler->GetPointerOffsets();
    ASSERT(pointer_offsets.length() == pointer_offset_count);
    ASSERT(code.pointer_offsets_length() == pointer_offsets.length());

    // Set pointer offsets list in Code object and resolve all handles in
    // the instruction stream to raw objects.
    for (intptr_t i = 0; i < pointer_offsets.length(); i++) {
      intptr_t offset_in_instrs = pointer_offsets[i];
      code.SetPointerOffsetAt(i, offset_in_instrs);
      uword addr = region.start() + offset_in_instrs;
      ASSERT(instrs.PayloadStart() <= addr);
      ASSERT((instrs.PayloadStart() + instrs.Size()) > addr);
      const Object* object = LoadUnaligned(reinterpret_cast<Object**>(addr));
      ASSERT(object->IsOld());
      // N.B. The pointer is embedded in the Instructions object, but visited
      // through the Code object.
      code.StorePointerUnaligned(reinterpret_cast<ObjectPtr*>(addr),
                                 object->ptr(), thread);
    }

    // Write protect instructions and, if supported by OS, use dual mapping
    // for execution.
    if (FLAG_write_protect_code) {
      // Note: when dual mapping is used we have separate RX and RW mappings.
      // RX mapping never changes protection while RW mapping flips between
      // R and RW.
      uword address = UntaggedObject::ToAddr(instrs.ptr());
      VirtualMemory::WriteProtectCode(reinterpret_cast<void*>(address),
                                      instrs.ptr()->untag()->HeapSize());
    }

    // Hook up Code and Instructions objects.
    const uword unchecked_offset = assembler->UncheckedEntryOffset();
    code.SetActiveInstructions(instrs, unchecked_offset);
    code.set_instructions(instrs);
    NOT_IN_PRECOMPILED(code.set_unchecked_offset(unchecked_offset));
    code.set_is_alive(true);

    // Set object pool in Instructions object.
    if (!object_pool.IsNull()) {
      code.set_object_pool(object_pool.ptr());
    }

#if defined(DART_PRECOMPILER)
    if (stats != nullptr) {
      stats->Finalize();
      instrs.set_stats(stats);
    }
#endif

    CPU::FlushICache(region.start(), region.size());
  }

#if defined(INCLUDE_IL_PRINTER)
  code.set_comments(CreateCommentsFrom(assembler));
#endif  // defined(INCLUDE_IL_PRINTER)

#ifndef PRODUCT
  code.set_compile_timestamp(OS::GetCurrentMonotonicMicros());
  if (assembler->prologue_offset() >= 0) {
    code.SetPrologueOffset(assembler->prologue_offset());
  } else {
    // No prologue was ever entered, optimistically assume nothing was ever
    // pushed onto the stack.
    code.SetPrologueOffset(assembler->CodeSize());
  }
#endif
  return code.ptr();
}

void Code::NotifyCodeObservers(const Code& code, bool optimized) {
#if !defined(PRODUCT)
  ASSERT(!Thread::Current()->OwnsGCSafepoint());
  if (CodeObservers::AreActive()) {
    if (code.IsFunctionCode()) {
      const auto& function = Function::Handle(code.function());
      if (!function.IsNull()) {
        return NotifyCodeObservers(function, code, optimized);
      }
    }
    NotifyCodeObservers(code.Name(), code, optimized);
  }
#endif
}

void Code::NotifyCodeObservers(const Function& function,
                               const Code& code,
                               bool optimized) {
#if !defined(PRODUCT)
  ASSERT(!function.IsNull());
  // Calling ToLibNamePrefixedQualifiedCString is very expensive,
  // try to avoid it.
  if (CodeObservers::AreActive()) {
    const char* name = function.ToLibNamePrefixedQualifiedCString();
    NotifyCodeObservers(name, code, optimized);
  }
#endif
}

void Code::NotifyCodeObservers(const char* name,
                               const Code& code,
                               bool optimized) {
#if !defined(PRODUCT)
  ASSERT(name != nullptr);
  ASSERT(!code.IsNull());
  if (CodeObservers::AreActive()) {
    const auto& instrs = Instructions::Handle(code.instructions());
    CodeObservers::NotifyAll(name, instrs.PayloadStart(),
                             code.GetPrologueOffset(), instrs.Size(), optimized,
                             &code.comments());
  }
#endif
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

CodePtr Code::FindCode(uword pc, int64_t timestamp) {
  class SlowFindCodeVisitor : public ObjectVisitor {
   public:
    SlowFindCodeVisitor(uword pc, int64_t timestamp)
        : pc_(pc), timestamp_(timestamp), result_(Code::null()) {}

    void VisitObject(ObjectPtr obj) {
      if (!obj->IsCode()) return;
      CodePtr code = static_cast<CodePtr>(obj);
      if (Code::PayloadStartOf(code) != pc_) return;
#if !defined(PRODUCT)
      if (code->untag()->compile_timestamp_ != timestamp_) return;
#endif
      ASSERT(result_ == Code::null());
      result_ = code;
    }

    CodePtr result() const { return result_; }

   private:
    uword pc_;
    int64_t timestamp_;
    CodePtr result_;
  };

  HeapIterationScope iteration(Thread::Current());
  SlowFindCodeVisitor visitor(pc, timestamp);
  iteration.IterateVMIsolateObjects(&visitor);
  iteration.IterateOldObjectsNoImagePages(&visitor);
  return visitor.result();
}

CodePtr Code::FindCodeUnsafe(uword pc) {
  class FindCodeUnsafeVisitor : public ObjectVisitor {
   public:
    explicit FindCodeUnsafeVisitor(uword pc) : pc_(pc), result_(Code::null()) {}

    void VisitObject(ObjectPtr obj) {
      if (obj->IsCode()) {
        CodePtr code = static_cast<CodePtr>(obj);
        if (Code::ContainsInstructionAt(code, pc_)) {
          result_ = code;
        }
      }
    }

    CodePtr result() { return result_; }

   private:
    uword pc_;
    CodePtr result_;
  };

  IsolateGroup* group = IsolateGroup::Current();
  PageSpace* old_space = group->heap()->old_space();
  old_space->MakeIterable();
  FindCodeUnsafeVisitor visitor(pc);
  old_space->VisitObjectsUnsafe(&visitor);
  Dart::vm_isolate_group()->heap()->old_space()->VisitObjectsUnsafe(&visitor);
  return visitor.result();
}

TokenPosition Code::GetTokenIndexOfPC(uword pc) const {
  uword pc_offset = pc - PayloadStart();
  const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
  PcDescriptors::Iterator iter(descriptors, UntaggedPcDescriptors::kAnyKind);
  while (iter.MoveNext()) {
    if (iter.PcOffset() == pc_offset) {
      return iter.TokenPos();
    }
  }
  return TokenPosition::kNoSource;
}

uword Code::GetPcForDeoptId(intptr_t deopt_id,
                            UntaggedPcDescriptors::Kind kind) const {
  const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
  PcDescriptors::Iterator iter(descriptors, kind);
  while (iter.MoveNext()) {
    if (iter.DeoptId() == deopt_id) {
      uword pc_offset = iter.PcOffset();
      uword pc = PayloadStart() + pc_offset;
      ASSERT(ContainsInstructionAt(pc));
      return pc;
    }
  }
  return 0;
}

intptr_t Code::GetDeoptIdForOsr(uword pc) const {
  uword pc_offset = pc - PayloadStart();
  const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
  PcDescriptors::Iterator iter(descriptors, UntaggedPcDescriptors::kOsrEntry);
  while (iter.MoveNext()) {
    if (iter.PcOffset() == pc_offset) {
      return iter.DeoptId();
    }
  }
  return DeoptId::kNone;
}

const char* Code::ToCString() const {
  return OS::SCreate(Thread::Current()->zone(), "Code(%s)",
                     QualifiedName(NameFormattingParams(
                         kScrubbedName, NameDisambiguation::kYes)));
}

uint32_t Code::Hash() const {
  // PayloadStart() is a tempting hash as Instructions are not moved by the
  // compactor, but Instructions are effectively moved between the process
  // creating an AppJIT/AOT snapshot and the process loading the snapshot.
  const Object& obj =
      Object::Handle(WeakSerializationReference::UnwrapIfTarget(owner()));
  if (obj.IsClass()) {
    return Class::Cast(obj).Hash();
  } else if (obj.IsAbstractType()) {
    return AbstractType::Cast(obj).Hash();
  } else if (obj.IsFunction()) {
    return Function::Cast(obj).Hash();
  } else {
    // E.g., VM stub.
    return 42;
  }
}

const char* Code::Name() const {
  Zone* zone = Thread::Current()->zone();
  if (IsStubCode()) {
    // Regular stub.
    const char* name = StubCode::NameOfStub(EntryPoint());
    if (name == nullptr) {
      return "[unknown stub]";  // Not yet recorded.
    }
    return OS::SCreate(zone, "[Stub] %s", name);
  }
  const auto& obj =
      Object::Handle(zone, WeakSerializationReference::UnwrapIfTarget(owner()));
  if (obj.IsClass()) {
    // Allocation stub.
    return OS::SCreate(zone, "[Stub] Allocate %s",
                       Class::Cast(obj).ScrubbedNameCString());
  } else if (obj.IsAbstractType()) {
    // Type test stub.
    return OS::SCreate(zone, "[Stub] Type Test %s",
                       AbstractType::Cast(obj).ToCString());
  } else if (obj.IsFunction()) {
    // Dart function.
    const char* opt = is_optimized() ? "[Optimized]" : "[Unoptimized]";
    const char* function_name = Function::Cast(obj).UserVisibleNameCString();
    return OS::SCreate(zone, "%s %s", opt, function_name);
  } else {
    // --no_retain_function_objects etc
    return "[unknown code]";
  }
}

const char* Code::QualifiedName(const NameFormattingParams& params) const {
  Zone* zone = Thread::Current()->zone();
  const Object& obj =
      Object::Handle(zone, WeakSerializationReference::UnwrapIfTarget(owner()));
  if (obj.IsFunction()) {
    ZoneTextBuffer printer(zone);
    printer.AddString(is_optimized() ? "[Optimized] " : "[Unoptimized] ");
    Function::Cast(obj).PrintName(params, &printer);
    return printer.buffer();
  }
  return Name();
}

bool Code::IsStubCode() const {
  // We should _not_ unwrap any possible WSRs here, as the null value is never
  // wrapped by a WSR.
  return owner() == Object::null();
}

bool Code::IsAllocationStubCode() const {
  return OwnerClassId() == kClassCid;
}

bool Code::IsTypeTestStubCode() const {
  auto const cid = OwnerClassId();
  return cid == kAbstractTypeCid || cid == kTypeCid ||
         cid == kFunctionTypeCid || cid == kRecordTypeCid ||
         cid == kTypeParameterCid;
}

bool Code::IsFunctionCode() const {
  return OwnerClassId() == kFunctionCid;
}

bool Code::IsUnknownDartCode(CodePtr code) {
  return StubCode::HasBeenInitialized() &&
         (code == StubCode::UnknownDartCode().ptr());
}

void Code::DisableDartCode() const {
  GcSafepointOperationScope safepoint(Thread::Current());
  ASSERT(IsFunctionCode());
  ASSERT(instructions() == active_instructions());
  const Code& new_code = StubCode::FixCallersTarget();
  SetActiveInstructions(Instructions::Handle(new_code.instructions()),
                        new_code.UncheckedEntryPointOffset());
}

void Code::DisableStubCode(bool is_cls_parameterized) const {
  GcSafepointOperationScope safepoint(Thread::Current());
  ASSERT(IsAllocationStubCode());
  ASSERT(instructions() == active_instructions());
  const Code& new_code = is_cls_parameterized
                             ? StubCode::FixParameterizedAllocationStubTarget()
                             : StubCode::FixAllocationStubTarget();
  SetActiveInstructions(Instructions::Handle(new_code.instructions()),
                        new_code.UncheckedEntryPointOffset());
}

void Code::InitializeCachedEntryPointsFrom(CodePtr code,
                                           InstructionsPtr instructions,
                                           uint32_t unchecked_offset) {
  NoSafepointScope _;
  const uword entry_point = Instructions::EntryPoint(instructions);
  const uword monomorphic_entry_point =
      Instructions::MonomorphicEntryPoint(instructions);
  code->untag()->entry_point_ = entry_point;
  code->untag()->monomorphic_entry_point_ = monomorphic_entry_point;
  code->untag()->unchecked_entry_point_ = entry_point + unchecked_offset;
  code->untag()->monomorphic_unchecked_entry_point_ =
      monomorphic_entry_point + unchecked_offset;
}

void Code::SetActiveInstructions(const Instructions& instructions,
                                 uint32_t unchecked_offset) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  SetActiveInstructionsSafe(instructions, unchecked_offset);
#endif
}

void Code::SetActiveInstructionsSafe(const Instructions& instructions,
                                     uint32_t unchecked_offset) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  // RawInstructions are never allocated in New space and hence a
  // store buffer update is not needed here.
  untag()->set_active_instructions(instructions.ptr());
  Code::InitializeCachedEntryPointsFrom(ptr(), instructions.ptr(),
                                        unchecked_offset);
#endif
}

void Code::ResetActiveInstructions() const {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  SetActiveInstructions(Instructions::Handle(instructions()),
                        untag()->unchecked_offset_);
#endif
}

void Code::GetInlinedFunctionsAtInstruction(
    intptr_t pc_offset,
    GrowableArray<const Function*>* functions,
    GrowableArray<TokenPosition>* token_positions) const {
  const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map());
  if (map.IsNull()) {
    ASSERT(!IsFunctionCode());
    return;  // VM stub, allocation stub, or type testing stub.
  }
  const Array& id_map = Array::Handle(inlined_id_to_function());
  const Function& root = Function::Handle(function());
  CodeSourceMapReader reader(map, id_map, root);
  reader.GetInlinedFunctionsAt(pc_offset, functions, token_positions);
}

#ifndef PRODUCT
void Code::PrintJSONInlineIntervals(JSONObject* jsobj) const {
  if (!is_optimized()) {
    return;  // No inlining.
  }
  const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map());
  const Array& id_map = Array::Handle(inlined_id_to_function());
  const Function& root = Function::Handle(function());
  CodeSourceMapReader reader(map, id_map, root);
  reader.PrintJSONInlineIntervals(jsobj);
}
#endif

void Code::DumpInlineIntervals() const {
  const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map());
  if (map.IsNull()) {
    // Stub code.
    return;
  }
  const Array& id_map = Array::Handle(inlined_id_to_function());
  const Function& root = Function::Handle(function());
  CodeSourceMapReader reader(map, id_map, root);
  reader.DumpInlineIntervals(PayloadStart());
}

void Code::DumpSourcePositions(bool relative_addresses) const {
  const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map());
  if (map.IsNull()) {
    // Stub code.
    return;
  }
  const Array& id_map = Array::Handle(inlined_id_to_function());
  const Function& root = Function::Handle(function());
  CodeSourceMapReader reader(map, id_map, root);
  reader.DumpSourcePositions(relative_addresses ? 0 : PayloadStart());
}

void Bytecode::Disassemble(DisassemblyFormatter* formatter) const {
#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
#if defined(DART_DYNAMIC_MODULES)
  if (!FLAG_support_disassembler) {
    return;
  }
  uword start = PayloadStart();
  intptr_t size = Size();
  if (formatter == NULL) {
    KernelBytecodeDisassembler::Disassemble(start, start + size, *this);
  } else {
    KernelBytecodeDisassembler::Disassemble(start, start + size, formatter,
                                            *this);
  }
#endif  // defined(DART_DYNAMIC_MODULES)
#endif  // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
}

BytecodePtr Bytecode::New(uword instructions,
                          intptr_t instructions_size,
                          intptr_t instructions_offset,
                          const TypedDataBase& binary,
                          const ObjectPool& object_pool) {
  ASSERT(Object::bytecode_class() != Class::null());
  Bytecode& result = Bytecode::Handle();
  {
    auto raw = Object::Allocate<Bytecode>(Heap::kOld);
    NoSafepointScope no_safepoint;
    result = raw;
    result.set_instructions(instructions);
    result.set_instructions_size(instructions_size);
    result.set_object_pool(object_pool);
    result.set_pc_descriptors(Object::empty_descriptors());
    result.set_binary(binary);
    result.set_instructions_binary_offset(instructions_offset);
    result.set_code_offset(0);
    result.set_source_positions_binary_offset(0);
  }
  return result.ptr();
}

TokenPosition Bytecode::GetTokenIndexOfPC(uword return_address) const {
#if defined(DART_DYNAMIC_MODULES)
  if (!HasSourcePositions()) {
    return TokenPosition::kNoSource;
  }
  Zone* zone = Thread::Current()->zone();
  uword pc_offset = return_address - PayloadStart();
  // pc_offset could equal to bytecode size if the last instruction is Throw.
  ASSERT(pc_offset <= static_cast<uword>(Size()));
  bytecode::BytecodeSourcePositionsIterator iter(zone, *this);
  TokenPosition token_pos = TokenPosition::kNoSource;
  while (iter.MoveNext()) {
    if (pc_offset <= iter.PcOffset()) {
      break;
    }
    token_pos = iter.TokenPos();
  }
  return token_pos;
#else
  UNREACHABLE();
#endif
}

intptr_t Bytecode::GetTryIndexAtPc(uword return_address) const {
#if defined(DART_DYNAMIC_MODULES)
  intptr_t try_index = -1;
  const uword pc_offset = return_address - PayloadStart();
  const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
  PcDescriptors::Iterator iter(descriptors, UntaggedPcDescriptors::kAnyKind);
  while (iter.MoveNext()) {
    // PC descriptors for try blocks in bytecode are generated in pairs,
    // marking start and end of a try block.
    // See BytecodeReaderHelper::ReadExceptionsTable for details.
    const intptr_t current_try_index = iter.TryIndex();
    const uword start_pc = iter.PcOffset();
    if (pc_offset < start_pc) {
      break;
    }
    const bool has_next = iter.MoveNext();
    ASSERT(has_next);
    const uword end_pc = iter.PcOffset();
    if (start_pc <= pc_offset && pc_offset < end_pc) {
      ASSERT(try_index < current_try_index);
      try_index = current_try_index;
    }
  }
  return try_index;
#else
  UNREACHABLE();
#endif
}

uword Bytecode::GetFirstDebugCheckOpcodePc() const {
#if defined(DART_DYNAMIC_MODULES)
  uword pc = PayloadStart();
  const uword end_pc = pc + Size();
  while (pc < end_pc) {
    if (KernelBytecode::IsDebugCheckOpcode(
            reinterpret_cast<const KBCInstr*>(pc))) {
      return pc;
    }
    pc = KernelBytecode::Next(pc);
  }
  return 0;
#else
  UNREACHABLE();
#endif
}

uword Bytecode::GetDebugCheckedOpcodeReturnAddress(uword from_offset,
                                                   uword to_offset) const {
#if defined(DART_DYNAMIC_MODULES)
  uword pc = PayloadStart() + from_offset;
  const uword end_pc = pc + (to_offset - from_offset);
  while (pc < end_pc) {
    uword next_pc = KernelBytecode::Next(pc);
    if (KernelBytecode::IsDebugCheckedOpcode(
            reinterpret_cast<const KBCInstr*>(pc))) {
      // Return the pc after the opcode, i.e. its 'return address'.
      return next_pc;
    }
    pc = next_pc;
  }
  return 0;
#else
  UNREACHABLE();
#endif
}

#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
LocalVarDescriptorsPtr Bytecode::GetLocalVarDescriptors() const {
#if defined(DART_DYNAMIC_MODULES)
  Zone* zone = Thread::Current()->zone();
  auto& var_descs = LocalVarDescriptors::Handle(zone, var_descriptors());
  if (var_descs.IsNull()) {
    const auto& func = Function::Handle(zone, function());
    ASSERT(!func.IsNull());
    var_descs =
        bytecode::BytecodeReader::ComputeLocalVarDescriptors(zone, func, *this);
    ASSERT(!var_descs.IsNull());
    set_var_descriptors(var_descs);
  }
  return var_descs.ptr();
#else
  UNREACHABLE();
#endif
}
#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

const char* Bytecode::ToCString() const {
  return Thread::Current()->zone()->PrintToString("Bytecode(%s)",
                                                  QualifiedName());
}

static const char* BytecodeStubName(const Bytecode& bytecode) {
  if (bytecode.ptr() == Object::implicit_getter_bytecode().ptr()) {
    return "[Bytecode Stub] VMInternal_ImplicitGetter";
  } else if (bytecode.ptr() == Object::implicit_setter_bytecode().ptr()) {
    return "[Bytecode Stub] VMInternal_ImplicitSetter";
  } else if (bytecode.ptr() ==
             Object::implicit_static_getter_bytecode().ptr()) {
    return "[Bytecode Stub] VMInternal_ImplicitStaticGetter";
  } else if (bytecode.ptr() ==
             Object::implicit_static_setter_bytecode().ptr()) {
    return "[Bytecode Stub] VMInternal_ImplicitStaticSetter";
  } else if (bytecode.ptr() == Object::method_extractor_bytecode().ptr()) {
    return "[Bytecode Stub] VMInternal_MethodExtractor";
  } else if (bytecode.ptr() == Object::invoke_closure_bytecode().ptr()) {
    return "[Bytecode Stub] VMInternal_InvokeClosure";
  } else if (bytecode.ptr() == Object::invoke_field_bytecode().ptr()) {
    return "[Bytecode Stub] VMInternal_InvokeField";
  }
  return "[unknown stub]";
}

const char* Bytecode::Name() const {
  Zone* zone = Thread::Current()->zone();
  const Function& fun = Function::Handle(zone, function());
  if (fun.IsNull()) {
    return BytecodeStubName(*this);
  }
  const char* function_name =
      String::Handle(zone, fun.UserVisibleName()).ToCString();
  return zone->PrintToString("[Bytecode] %s", function_name);
}

const char* Bytecode::QualifiedName() const {
  Zone* zone = Thread::Current()->zone();
  const Function& fun = Function::Handle(zone, function());
  if (fun.IsNull()) {
    return BytecodeStubName(*this);
  }
  const char* function_name =
      String::Handle(zone, fun.QualifiedScrubbedName()).ToCString();
  return zone->PrintToString("[Bytecode] %s", function_name);
}

const char* Bytecode::FullyQualifiedName() const {
  Zone* zone = Thread::Current()->zone();
  const Function& fun = Function::Handle(zone, function());
  if (fun.IsNull()) {
    return BytecodeStubName(*this);
  }
  const char* function_name = fun.ToFullyQualifiedCString();
  return zone->PrintToString("[Bytecode] %s", function_name);
}

void Bytecode::set_binary(const TypedDataBase& binary) const {
  ASSERT(binary.IsNull() || binary.IsExternalOrExternalView());
  untag()->set_binary(binary.ptr());
}

intptr_t Context::GetLevel() const {
  intptr_t level = 0;
  Context& parent_ctx = Context::Handle(parent());
  while (!parent_ctx.IsNull()) {
    level++;
    parent_ctx = parent_ctx.parent();
  }
  return level;
}

ContextPtr Context::New(intptr_t num_variables, Heap::Space space) {
  ASSERT(num_variables >= 0);
  ASSERT(Object::context_class() != Class::null());

  if (!IsValidLength(num_variables)) {
    // This should be caught before we reach here.
    FATAL("Fatal error in Context::New: invalid num_variables %" Pd "\n",
          num_variables);
  }
  auto raw = Object::Allocate<Context>(space, num_variables);
  NoSafepointScope no_safepoint;
  raw->untag()->num_variables_ = num_variables;
  return raw;
}

const char* Context::ToCString() const {
  if (IsNull()) {
    return "Context: null";
  }
  Zone* zone = Thread::Current()->zone();
  const Context& parent_ctx = Context::Handle(parent());
  if (parent_ctx.IsNull()) {
    return zone->PrintToString("Context num_variables: %" Pd "",
                               num_variables());
  } else {
    const char* parent_str = parent_ctx.ToCString();
    return zone->PrintToString("Context num_variables: %" Pd " parent:{ %s }",
                               num_variables(), parent_str);
  }
}

static void IndentN(int count) {
  for (int i = 0; i < count; i++) {
    THR_Print(" ");
  }
}

void Context::Dump(int indent) const {
  if (IsNull()) {
    IndentN(indent);
    THR_Print("Context@null\n");
    return;
  }

  IndentN(indent);
  THR_Print("Context vars(%" Pd ") {\n", num_variables());
  Object& obj = Object::Handle();
  for (intptr_t i = 0; i < num_variables(); i++) {
    IndentN(indent + 2);
    obj = At(i);
    const char* s = obj.ToCString();
    if (strlen(s) > 50) {
      THR_Print("[%" Pd "] = [first 50 chars:] %.50s...\n", i, s);
    } else {
      THR_Print("[%" Pd "] = %s\n", i, s);
    }
  }

  const Context& parent_ctx = Context::Handle(parent());
  if (!parent_ctx.IsNull()) {
    parent_ctx.Dump(indent + 2);
  }
  IndentN(indent);
  THR_Print("}\n");
}

ContextScopePtr ContextScope::New(intptr_t num_variables, bool is_implicit) {
  ASSERT(Object::context_scope_class() != Class::null());
  if (num_variables < 0 || num_variables > kMaxElements) {
    // This should be caught before we reach here.
    FATAL("Fatal error in ContextScope::New: invalid num_variables %" Pd "\n",
          num_variables);
  }
  ContextScope& result = ContextScope::Handle();
  {
    auto raw = Object::Allocate<ContextScope>(Heap::kOld, num_variables);
    NoSafepointScope no_safepoint;
    result = raw;
    result.set_num_variables(num_variables);
  }
  result.set_is_implicit(is_implicit);
  return result.ptr();
}

TokenPosition ContextScope::TokenIndexAt(intptr_t scope_index) const {
  return TokenPosition::Deserialize(
      Smi::Value(untag()->token_pos_at(scope_index)));
}

void ContextScope::SetTokenIndexAt(intptr_t scope_index,
                                   TokenPosition token_pos) const {
  untag()->set_token_pos_at(scope_index, Smi::New(token_pos.Serialize()));
}

TokenPosition ContextScope::DeclarationTokenIndexAt(
    intptr_t scope_index) const {
  return TokenPosition::Deserialize(
      Smi::Value(untag()->declaration_token_pos_at(scope_index)));
}

void ContextScope::SetDeclarationTokenIndexAt(
    intptr_t scope_index,
    TokenPosition declaration_token_pos) const {
  untag()->set_declaration_token_pos_at(
      scope_index, Smi::New(declaration_token_pos.Serialize()));
}

StringPtr ContextScope::NameAt(intptr_t scope_index) const {
  return untag()->name_at(scope_index);
}

void ContextScope::SetNameAt(intptr_t scope_index, const String& name) const {
  untag()->set_name_at(scope_index, name.ptr());
}

void ContextScope::ClearFlagsAt(intptr_t scope_index) const {
  untag()->set_flags_at(scope_index, Smi::New(0));
}

bool ContextScope::GetFlagAt(intptr_t scope_index, intptr_t bit_index) const {
  const intptr_t mask = 1 << bit_index;
  return (Smi::Value(untag()->flags_at(scope_index)) & mask) != 0;
}

void ContextScope::SetFlagAt(intptr_t scope_index,
                             intptr_t bit_index,
                             bool value) const {
  const intptr_t mask = 1 << bit_index;
  intptr_t flags = Smi::Value(untag()->flags_at(scope_index));
  untag()->set_flags_at(scope_index,
                        Smi::New(value ? flags | mask : flags & ~mask));
}

#define DEFINE_FLAG_ACCESSORS(Name)                                            \
  bool ContextScope::Is##Name##At(intptr_t scope_index) const {                \
    return GetFlagAt(scope_index,                                              \
                     UntaggedContextScope::VariableDesc::kIs##Name);           \
  }                                                                            \
                                                                               \
  void ContextScope::SetIs##Name##At(intptr_t scope_index, bool value) const { \
    SetFlagAt(scope_index, UntaggedContextScope::VariableDesc::kIs##Name,      \
              value);                                                          \
  }

CONTEXT_SCOPE_VARIABLE_DESC_FLAG_LIST(DEFINE_FLAG_ACCESSORS)
#undef DEFINE_FLAG_ACCESSORS

intptr_t ContextScope::LateInitOffsetAt(intptr_t scope_index) const {
  return Smi::Value(untag()->late_init_offset_at(scope_index));
}

void ContextScope::SetLateInitOffsetAt(intptr_t scope_index,
                                       intptr_t late_init_offset) const {
  untag()->set_late_init_offset_at(scope_index, Smi::New(late_init_offset));
}

AbstractTypePtr ContextScope::TypeAt(intptr_t scope_index) const {
  return untag()->type_at(scope_index);
}

void ContextScope::SetTypeAt(intptr_t scope_index,
                             const AbstractType& type) const {
  untag()->set_type_at(scope_index, type.ptr());
}

intptr_t ContextScope::CidAt(intptr_t scope_index) const {
  return Smi::Value(untag()->cid_at(scope_index));
}

void ContextScope::SetCidAt(intptr_t scope_index, intptr_t cid) const {
  untag()->set_cid_at(scope_index, Smi::New(cid));
}

intptr_t ContextScope::ContextIndexAt(intptr_t scope_index) const {
  return Smi::Value(untag()->context_index_at(scope_index));
}

void ContextScope::SetContextIndexAt(intptr_t scope_index,
                                     intptr_t context_index) const {
  untag()->set_context_index_at(scope_index, Smi::New(context_index));
}

intptr_t ContextScope::ContextLevelAt(intptr_t scope_index) const {
  return Smi::Value(untag()->context_level_at(scope_index));
}

void ContextScope::SetContextLevelAt(intptr_t scope_index,
                                     intptr_t context_level) const {
  untag()->set_context_level_at(scope_index, Smi::New(context_level));
}

intptr_t ContextScope::KernelOffsetAt(intptr_t scope_index) const {
  return Smi::Value(untag()->kernel_offset_at(scope_index));
}

void ContextScope::SetKernelOffsetAt(intptr_t scope_index,
                                     intptr_t kernel_offset) const {
  untag()->set_kernel_offset_at(scope_index, Smi::New(kernel_offset));
}

const char* ContextScope::ToCString() const {
  const char* prev_cstr = "ContextScope:";
  String& name = String::Handle();
  for (int i = 0; i < num_variables(); i++) {
    name = NameAt(i);
    const char* cname = name.ToCString();
    TokenPosition pos = TokenIndexAt(i);
    intptr_t idx = ContextIndexAt(i);
    intptr_t lvl = ContextLevelAt(i);
    char* chars =
        OS::SCreate(Thread::Current()->zone(),
                    "%s\nvar %s  token-pos %s  ctx lvl %" Pd "  index %" Pd "",
                    prev_cstr, cname, pos.ToCString(), lvl, idx);
    prev_cstr = chars;
  }
  return prev_cstr;
}

SentinelPtr Sentinel::New() {
  return Object::Allocate<Sentinel>(Heap::kOld);
}

const char* Sentinel::ToCString() const {
  if (ptr() == Object::sentinel().ptr()) {
    return "sentinel";
  } else if (ptr() == Object::unknown_constant().ptr()) {
    return "unknown_constant";
  } else if (ptr() == Object::non_constant().ptr()) {
    return "non_constant";
  } else if (ptr() == Object::optimized_out().ptr()) {
    return "<optimized out>";
  }
  return "Sentinel(unknown)";
}

ArrayPtr MegamorphicCache::buckets() const {
  return untag()->buckets();
}

void MegamorphicCache::set_buckets(const Array& buckets) const {
  untag()->set_buckets(buckets.ptr());
}

// Class IDs in the table are smi-tagged, so we use a smi-tagged mask
// and target class ID to avoid untagging (on each iteration of the
// test loop) in generated code.
intptr_t MegamorphicCache::mask() const {
  return Smi::Value(untag()->mask());
}

void MegamorphicCache::set_mask(intptr_t mask) const {
  untag()->set_mask(Smi::New(mask));
}

intptr_t MegamorphicCache::filled_entry_count() const {
  return untag()->filled_entry_count_;
}

void MegamorphicCache::set_filled_entry_count(intptr_t count) const {
  StoreNonPointer(&untag()->filled_entry_count_, count);
}

MegamorphicCachePtr MegamorphicCache::New() {
  return Object::Allocate<MegamorphicCache>(Heap::kOld);
}

MegamorphicCachePtr MegamorphicCache::New(const String& target_name,
                                          const Array& arguments_descriptor) {
  auto* const zone = Thread::Current()->zone();
  const auto& result = MegamorphicCache::Handle(
      zone, Object::Allocate<MegamorphicCache>(Heap::kOld));
  const intptr_t capacity = kInitialCapacity;
  const Array& buckets =
      Array::Handle(zone, Array::New(kEntryLength * capacity, Heap::kOld));
  const Object& handler = Object::Handle(zone);
  for (intptr_t i = 0; i < capacity; ++i) {
    SetEntry(buckets, i, smi_illegal_cid(), handler);
  }
  result.set_buckets(buckets);
  result.set_mask(capacity - 1);
  result.set_target_name(target_name);
  result.set_arguments_descriptor(arguments_descriptor);
  result.set_filled_entry_count(0);
  return result.ptr();
}

void MegamorphicCache::EnsureContains(const Smi& class_id,
                                      const Object& target) const {
  SafepointMutexLocker ml(IsolateGroup::Current()->type_feedback_mutex());

  if (LookupLocked(class_id) == Object::null()) {
    InsertLocked(class_id, target);
  }

#if defined(DEBUG)
  ASSERT(LookupLocked(class_id) == target.ptr());
#endif  // define(DEBUG)
}

ObjectPtr MegamorphicCache::Lookup(const Smi& class_id) const {
  SafepointMutexLocker ml(IsolateGroup::Current()->type_feedback_mutex());
  return LookupLocked(class_id);
}

ObjectPtr MegamorphicCache::LookupLocked(const Smi& class_id) const {
  auto thread = Thread::Current();
  auto isolate_group = thread->isolate_group();
  auto zone = thread->zone();
  ASSERT(thread->IsDartMutatorThread());
  ASSERT(isolate_group->type_feedback_mutex()->IsOwnedByCurrentThread());

  const auto& backing_array = Array::Handle(zone, buckets());
  intptr_t id_mask = mask();
  intptr_t index = (class_id.Value() * kSpreadFactor) & id_mask;
  intptr_t i = index;
  do {
    const classid_t current_cid =
        Smi::Value(Smi::RawCast(GetClassId(backing_array, i)));
    if (current_cid == class_id.Value()) {
      return GetTargetFunction(backing_array, i);
    } else if (current_cid == kIllegalCid) {
      return Object::null();
    }
    i = (i + 1) & id_mask;
  } while (i != index);
  UNREACHABLE();
}

// Note this may run with Dart execution reading this cache.
void MegamorphicCache::InsertLocked(const Smi& class_id,
                                    const Object& target) const {
  auto thread = Thread::Current();
  auto zone = thread->zone();
  auto isolate_group = thread->isolate_group();
  ASSERT(isolate_group->type_feedback_mutex()->IsOwnedByCurrentThread());

  intptr_t old_capacity = mask() + 1;
  double load_limit = kLoadFactor * static_cast<double>(old_capacity);
  if (static_cast<double>(filled_entry_count() + 1) > load_limit) {
    const Array& old_buckets = Array::Handle(zone, buckets());
    intptr_t new_capacity = old_capacity * 2;
    intptr_t new_mask = new_capacity - 1;
    const Array& new_buckets =
        Array::Handle(zone, Array::New(kEntryLength * new_capacity));

    auto& target = Object::Handle(zone);
    for (intptr_t i = 0; i < new_capacity; ++i) {
      SetEntry(new_buckets, i, smi_illegal_cid(), target);
    }

    // Rehash the valid entries.
    Smi& class_id = Smi::Handle(zone);
    for (intptr_t i = 0; i < old_capacity; ++i) {
      class_id ^= GetClassId(old_buckets, i);
      if (class_id.Value() != kIllegalCid) {
        target = GetTargetFunction(old_buckets, i);
        InsertEntryLocked<std::memory_order_relaxed>(new_buckets, new_mask,
                                                     class_id, target);
      }
    }

    // Publish buckets first. Old mask with new buckets is just a spurious miss.
    untag()->set_buckets<std::memory_order_release>(new_buckets.ptr());
    untag()->set_mask<std::memory_order_release>(Smi::New(new_mask));
  }

  const Array& new_buckets = Array::Handle(zone, buckets());
  InsertEntryLocked<std::memory_order_release>(new_buckets, mask(), class_id,
                                               target);
  set_filled_entry_count(filled_entry_count() + 1);
}

template <std::memory_order order>
void MegamorphicCache::InsertEntryLocked(const Array& backing_array,
                                         intptr_t mask,
                                         const Smi& class_id,
                                         const Object& target) {
  const intptr_t start = (class_id.Value() * kSpreadFactor) & mask;
  intptr_t i = start;
  do {
    if (Smi::Value(Smi::RawCast(GetClassId(backing_array, i))) == kIllegalCid) {
      // Publish target first. Old class id with new target is just a spurious
      // miss.
      SetTargetFunction<order>(backing_array, i, target);
      SetClassId<order>(backing_array, i, class_id);
      return;
    }
    i = (i + 1) & mask;
  } while (i != start);
  UNREACHABLE();
}

const char* MegamorphicCache::ToCString() const {
  const String& name = String::Handle(target_name());
  return OS::SCreate(Thread::Current()->zone(), "MegamorphicCache(%s)",
                     name.ToCString());
}

SubtypeTestCachePtr SubtypeTestCache::New(intptr_t num_inputs) {
  ASSERT(Object::subtypetestcache_class() != Class::null());
  ASSERT(num_inputs >= 1);
  ASSERT(num_inputs <= kMaxInputs);
  // SubtypeTestCache objects are long living objects, allocate them in the
  // old generation.
  const auto& result =
      SubtypeTestCache::Handle(Object::Allocate<SubtypeTestCache>(Heap::kOld));
  ASSERT_EQUAL(result.num_occupied(), 0);
  result.untag()->num_inputs_ = num_inputs;
  result.set_cache(Object::empty_subtype_test_cache_array());
  return result.ptr();
}

ArrayPtr SubtypeTestCache::cache() const {
  return untag()->cache<std::memory_order_acquire>();
}

void SubtypeTestCache::set_cache(const Array& value) const {
  // We have to ensure that initializing stores to the array are available
  // when releasing the pointer to the array pointer.
  // => We have to use store-release here.
  untag()->set_cache<std::memory_order_release>(value.ptr());
}

void SubtypeTestCache::set_num_occupied(intptr_t value) const {
  ASSERT(Utils::IsUint(32, value));
  untag()->num_occupied_ = value;
}

intptr_t SubtypeTestCache::NumberOfChecks() const {
  ASSERT(!IsNull());
  return num_occupied();
}

intptr_t SubtypeTestCache::NumEntries() const {
  ASSERT(!IsNull());
  return Array::LengthOf(cache()) / kTestEntryLength;
}

intptr_t SubtypeTestCache::NumEntries(const Array& array) {
  SubtypeTestCacheTable table(array);
  return table.Length();
}

bool SubtypeTestCache::IsHash() const {
  if (IsNull()) return false;
  return Array::LengthOf(cache()) > kMaxLinearCacheSize;
}

bool SubtypeTestCache::IsHash(const Array& array) {
  return array.Length() > kMaxLinearCacheSize;
}

intptr_t SubtypeTestCache::AddCheck(
    const Object& instance_class_id_or_signature,
    const AbstractType& destination_type,
    const TypeArguments& instance_type_arguments,
    const TypeArguments& instantiator_type_arguments,
    const TypeArguments& function_type_arguments,
    const TypeArguments& instance_parent_function_type_arguments,
    const TypeArguments& instance_delayed_type_arguments,
    const Bool& test_result) const {
  ASSERT(Thread::Current()
             ->isolate_group()
             ->subtype_test_cache_mutex()
             ->IsOwnedByCurrentThread());
  ASSERT(!test_result.IsNull());
  ASSERT(Smi::New(kRecordCid) != instance_class_id_or_signature.ptr());

  const intptr_t old_num = NumberOfChecks();
  Zone* const zone = Thread::Current()->zone();
  Array& data = Array::Handle(zone, cache());
  bool was_grown;
  data = EnsureCapacity(zone, data, old_num + 1, &was_grown);
  ASSERT(data.ptr() != Object::empty_subtype_test_cache_array().ptr());

  const auto& loc = FindKeyOrUnused(
      data, num_inputs(), instance_class_id_or_signature, destination_type,
      instance_type_arguments, instantiator_type_arguments,
      function_type_arguments, instance_parent_function_type_arguments,
      instance_delayed_type_arguments);
  SubtypeTestCacheTable entries(data);
  const auto& entry = entries[loc.entry];
  if (loc.present) {
    if (entry.Get<kTestResult>() != test_result.ptr()) {
      const auto& old_result = Bool::Handle(zone, entry.Get<kTestResult>());
      FATAL("Existing subtype test cache entry has result %s, not %s",
            old_result.ToCString(), test_result.ToCString());
    }
    return loc.entry;
  }

  // Set the used elements in the entry in reverse order, so that the instance
  // cid or signature is last, then increment the number of entries.
  entry.Set<kTestResult>(test_result);
  switch (num_inputs()) {
    case 7:
      entry.Set<kDestinationType>(destination_type);
      FALL_THROUGH;
    case 6:
      entry.Set<kInstanceDelayedFunctionTypeArguments>(
          instance_delayed_type_arguments);
      FALL_THROUGH;
    case 5:
      entry.Set<kInstanceParentFunctionTypeArguments>(
          instance_parent_function_type_arguments);
      FALL_THROUGH;
    case 4:
      entry.Set<kFunctionTypeArguments>(function_type_arguments);
      FALL_THROUGH;
    case 3:
      entry.Set<kInstantiatorTypeArguments>(instantiator_type_arguments);
      FALL_THROUGH;
    case 2:
      entry.Set<kInstanceTypeArguments>(instance_type_arguments);
      FALL_THROUGH;
    case 1:
      // If this is a new backing array, we don't need store-release barriers,
      // as no reader has access to the array until it is set as the backing
      // store (which is done with a store-release barrier).
      //
      // Otherwise, the instance cid or signature must be set last with a
      // store-release barrier, so concurrent readers can depend on a non-null
      // value meaning the rest of the entry is safe to load without barriers.
      if (was_grown) {
        entry.Set<kInstanceCidOrSignature>(instance_class_id_or_signature);
      } else {
        entry.Set<kInstanceCidOrSignature, std::memory_order_release>(
            instance_class_id_or_signature);
      }
      break;
    default:
      UNREACHABLE();
  }
  set_num_occupied(old_num + 1);
  if (was_grown) {
    set_cache(data);
  }
  return loc.entry;
}

static inline bool SubtypeTestCacheEntryMatches(
    const SubtypeTestCacheTable::TupleView& t,
    intptr_t num_inputs,
    const Object& instance_class_id_or_signature,
    const AbstractType& destination_type,
    const TypeArguments& instance_type_arguments,
    const TypeArguments& instantiator_type_arguments,
    const TypeArguments& function_type_arguments,
    const TypeArguments& instance_parent_function_type_arguments,
    const TypeArguments& instance_delayed_type_arguments) {
  switch (num_inputs) {
    case 7:
      if (t.Get<SubtypeTestCache::kDestinationType>() !=
          destination_type.ptr()) {
        return false;
      }
      FALL_THROUGH;
    case 6:
      if (t.Get<SubtypeTestCache::kInstanceDelayedFunctionTypeArguments>() !=
          instance_delayed_type_arguments.ptr()) {
        return false;
      }
      FALL_THROUGH;
    case 5:
      if (t.Get<SubtypeTestCache::kInstanceParentFunctionTypeArguments>() !=
          instance_parent_function_type_arguments.ptr()) {
        return false;
      }
      FALL_THROUGH;
    case 4:
      if (t.Get<SubtypeTestCache::kFunctionTypeArguments>() !=
          function_type_arguments.ptr()) {
        return false;
      }
      FALL_THROUGH;
    case 3:
      if (t.Get<SubtypeTestCache::kInstantiatorTypeArguments>() !=
          instantiator_type_arguments.ptr()) {
        return false;
      }
      FALL_THROUGH;
    case 2:
      if (t.Get<SubtypeTestCache::kInstanceTypeArguments>() !=
          instance_type_arguments.ptr()) {
        return false;
      }
      FALL_THROUGH;
    case 1:
      // We don't need to perform load-acquire semantics when re-retrieving
      // the kInstanceCidOrSignature field, as this is performed only if the
      // entry is occupied, and occupied entries never change.
      return t.Get<SubtypeTestCache::kInstanceCidOrSignature>() ==
             instance_class_id_or_signature.ptr();
    default:
      UNREACHABLE();
  }
}

SubtypeTestCache::KeyLocation SubtypeTestCache::FindKeyOrUnused(
    const Array& array,
    intptr_t num_inputs,
    const Object& instance_class_id_or_signature,
    const AbstractType& destination_type,
    const TypeArguments& instance_type_arguments,
    const TypeArguments& instantiator_type_arguments,
    const TypeArguments& function_type_arguments,
    const TypeArguments& instance_parent_function_type_arguments,
    const TypeArguments& instance_delayed_type_arguments) {
  // Fast case for empty STCs.
  if (array.ptr() == Object::empty_subtype_test_cache_array().ptr()) {
    return {0, false};
  }
  const bool is_hash = IsHash(array);
  SubtypeTestCacheTable table(array);
  const intptr_t num_entries = table.Length();
  // For a linear cache, start at the first entry and probe linearly. This can
  // be done because a linear cache always has at least one unoccupied entry
  // after all the occupied ones.
  intptr_t probe = 0;
  intptr_t probe_distance = 1;
  if (is_hash) {
    // For a hash-based cache, instead start at an entry determined by the hash
    // of the keys.
    //
    // If we have an instance cid, then just use that as our starting hash.
    uint32_t hash =
        instance_class_id_or_signature.IsFunctionType()
            ? FunctionType::Cast(instance_class_id_or_signature).Hash()
            : Smi::Cast(instance_class_id_or_signature).Value();
    switch (num_inputs) {
      case 7:
        hash = CombineHashes(hash, destination_type.Hash());
        FALL_THROUGH;
      case 6:
        hash = CombineHashes(hash, instance_delayed_type_arguments.Hash());
        FALL_THROUGH;
      case 5:
        hash =
            CombineHashes(hash, instance_parent_function_type_arguments.Hash());
        FALL_THROUGH;
      case 4:
        hash = CombineHashes(hash, function_type_arguments.Hash());
        FALL_THROUGH;
      case 3:
        hash = CombineHashes(hash, instantiator_type_arguments.Hash());
        FALL_THROUGH;
      case 2:
        hash = CombineHashes(hash, instance_type_arguments.Hash());
        FALL_THROUGH;
      case 1:
        break;
      default:
        UNREACHABLE();
    }
    hash = FinalizeHash(hash);
    probe = hash & (num_entries - 1);
  }
  while (true) {
    const auto& tuple = table.At(probe);
    if (tuple.Get<kInstanceCidOrSignature, std::memory_order_acquire>() ==
        Object::null()) {
      break;
    }
    if (SubtypeTestCacheEntryMatches(
            tuple, num_inputs, instance_class_id_or_signature, destination_type,
            instance_type_arguments, instantiator_type_arguments,
            function_type_arguments, instance_parent_function_type_arguments,
            instance_delayed_type_arguments)) {
      return {probe, true};
    }
    // Advance probe by the current probing distance.
    probe = probe + probe_distance;
    if (is_hash) {
      // Wrap around if the probe goes off the end of the entries array.
      probe = probe & (num_entries - 1);
      // We had a collision, so increase the probe distance. See comment in
      // EnsureCapacityLocked for an explanation of how this hits all slots.
      probe_distance++;
    }
  }
  return {probe, false};
}

ArrayPtr SubtypeTestCache::EnsureCapacity(Zone* zone,
                                          const Array& array,
                                          intptr_t new_occupied,
                                          bool* was_grown) const {
  ASSERT(new_occupied > NumberOfChecks());
  ASSERT(was_grown != nullptr);
  // How many entries are in the current array (including unoccupied entries).
  const intptr_t current_capacity = NumEntries(array);

  // Early returns for cases where no growth is needed.
  *was_grown = false;
  const bool is_linear = IsLinear(array);
  if (is_linear) {
    // We need at least one unoccupied entry in addition to the occupied ones.
    if (current_capacity > new_occupied) return array.ptr();
  } else {
    if (LoadFactor(new_occupied, current_capacity) < kMaxLoadFactor) {
      return array.ptr();
    }
  }

  // Every path from here should result in a new backing array.
  *was_grown = true;
  // Initially null for initializing unoccupied entries.
  auto& instance_cid_or_signature = Object::Handle(zone);
  if (new_occupied <= kMaxLinearCacheEntries) {
    ASSERT(is_linear);
    // Not enough room for both the new entry and at least one unoccupied
    // entry, so grow the tuple capacity of the linear cache by about 50%,
    // ensuring that space for at least one new tuple is added, capping the
    // total number of occupied entries to the max allowed.
    const intptr_t new_capacity =
        Utils::Minimum(current_capacity + (current_capacity >> 1),
                       kMaxLinearCacheEntries) +
        1;
    const intptr_t cache_size = new_capacity * kTestEntryLength;
    ASSERT(cache_size <= kMaxLinearCacheSize);
    const auto& new_data =
        Array::Handle(zone, Array::Grow(array, cache_size, Heap::kOld));
    ASSERT(!new_data.IsNull());
    // No need to adjust old entries, as they are copied over by Array::Grow.
    // Just mark any new entries as unoccupied.
    SubtypeTestCacheTable table(new_data);
    for (intptr_t i = current_capacity; i < new_capacity; i++) {
      const auto& tuple = table.At(i);
      tuple.Set<kInstanceCidOrSignature>(instance_cid_or_signature);
    }
    return new_data.ptr();
  }

  // Either we're converting a linear cache into a hash-based cache, or the
  // load factor of the hash-based cache has increased to the point where we
  // need to grow it.
  const intptr_t new_capacity =
      is_linear ? kNumInitialHashCacheEntries : 2 * current_capacity;
  // Because we use quadratic (actually triangle number) probing it is
  // important that the size is a power of two (otherwise we could fail to
  // find an empty slot).  This is described in Knuth's The Art of Computer
  // Programming Volume 2, Chapter 6.4, exercise 20 (solution in the
  // appendix, 2nd edition).
  //
  // This is also important because when we do hash probing, we take the
  // calculated hash from the inputs and then calculate (hash % capacity) to get
  // the initial probe index. To ensure this is a fast calculation in the stubs,
  // we ensure the capacity is a power of 2, which allows (hash % capacity) to
  // be calculated as (hash & (capacity - 1)).
  ASSERT(Utils::IsPowerOfTwo(new_capacity));
  ASSERT(LoadFactor(new_occupied, new_capacity) < kMaxLoadFactor);
  const intptr_t new_size = new_capacity * kTestEntryLength;
  const auto& new_data =
      Array::Handle(zone, Array::NewUninitialized(new_size, Heap::kOld));
  ASSERT(!new_data.IsNull());
  // Mark all the entries in new_data as unoccupied.
  SubtypeTestCacheTable to_table(new_data);
  for (const auto& tuple : to_table) {
    tuple.Set<kInstanceCidOrSignature>(instance_cid_or_signature);
  }
  // Finally, copy over the entries.
  auto& destination_type = AbstractType::Handle(zone);
  auto& instance_type_arguments = TypeArguments::Handle(zone);
  auto& instantiator_type_arguments = TypeArguments::Handle(zone);
  auto& function_type_arguments = TypeArguments::Handle(zone);
  auto& instance_parent_function_type_arguments = TypeArguments::Handle(zone);
  auto& instance_delayed_type_arguments = TypeArguments::Handle(zone);
  auto& test_result = Bool::Handle(zone);
  const SubtypeTestCacheTable from_table(array);
  const intptr_t used_inputs = num_inputs();
  for (intptr_t i = 0; i < current_capacity; i++) {
    const auto& from_tuple = from_table.At(i);
    // Skip unoccupied entries.
    if (from_tuple.Get<kInstanceCidOrSignature>() == Object::null()) continue;
    GetCheckFromArray(array, used_inputs, i, &instance_cid_or_signature,
                      &destination_type, &instance_type_arguments,
                      &instantiator_type_arguments, &function_type_arguments,
                      &instance_parent_function_type_arguments,
                      &instance_delayed_type_arguments, &test_result);
    // Since new_data has a different total capacity, we can't use the old
    // entry indexes, but must recalculate them.
    auto loc = FindKeyOrUnused(
        new_data, used_inputs, instance_cid_or_signature, destination_type,
        instance_type_arguments, instantiator_type_arguments,
        function_type_arguments, instance_parent_function_type_arguments,
        instance_delayed_type_arguments);
    ASSERT(!loc.present);
    const auto& to_tuple = to_table.At(loc.entry);
    to_tuple.Set<kTestResult>(test_result);
    switch (used_inputs) {
      case 7:
        to_tuple.Set<kDestinationType>(destination_type);
        FALL_THROUGH;
      case 6:
        to_tuple.Set<kInstanceDelayedFunctionTypeArguments>(
            instance_delayed_type_arguments);
        FALL_THROUGH;
      case 5:
        to_tuple.Set<kInstanceParentFunctionTypeArguments>(
            instance_parent_function_type_arguments);
        FALL_THROUGH;
      case 4:
        to_tuple.Set<kFunctionTypeArguments>(function_type_arguments);
        FALL_THROUGH;
      case 3:
        to_tuple.Set<kInstantiatorTypeArguments>(instantiator_type_arguments);
        FALL_THROUGH;
      case 2:
        to_tuple.Set<kInstanceTypeArguments>(instance_type_arguments);
        FALL_THROUGH;
      case 1:
        to_tuple.Set<kInstanceCidOrSignature>(instance_cid_or_signature);
        break;
      default:
        UNREACHABLE();
    }
  }
  return new_data.ptr();
}

void SubtypeTestCache::GetCheck(
    intptr_t ix,
    Object* instance_class_id_or_signature,
    AbstractType* destination_type,
    TypeArguments* instance_type_arguments,
    TypeArguments* instantiator_type_arguments,
    TypeArguments* function_type_arguments,
    TypeArguments* instance_parent_function_type_arguments,
    TypeArguments* instance_delayed_type_arguments,
    Bool* test_result) const {
  ASSERT(Thread::Current()
             ->isolate_group()
             ->subtype_test_cache_mutex()
             ->IsOwnedByCurrentThread());
  GetCurrentCheck(ix, instance_class_id_or_signature, destination_type,
                  instance_type_arguments, instantiator_type_arguments,
                  function_type_arguments,
                  instance_parent_function_type_arguments,
                  instance_delayed_type_arguments, test_result);
}

void SubtypeTestCache::GetCurrentCheck(
    intptr_t ix,
    Object* instance_class_id_or_signature,
    AbstractType* destination_type,
    TypeArguments* instance_type_arguments,
    TypeArguments* instantiator_type_arguments,
    TypeArguments* function_type_arguments,
    TypeArguments* instance_parent_function_type_arguments,
    TypeArguments* instance_delayed_type_arguments,
    Bool* test_result) const {
  const Array& array = Array::Handle(cache());
  GetCheckFromArray(array, num_inputs(), ix, instance_class_id_or_signature,
                    destination_type, instance_type_arguments,
                    instantiator_type_arguments, function_type_arguments,
                    instance_parent_function_type_arguments,
                    instance_delayed_type_arguments, test_result);
}

void SubtypeTestCache::GetCheckFromArray(
    const Array& array,
    intptr_t num_inputs,
    intptr_t ix,
    Object* instance_class_id_or_signature,
    AbstractType* destination_type,
    TypeArguments* instance_type_arguments,
    TypeArguments* instantiator_type_arguments,
    TypeArguments* function_type_arguments,
    TypeArguments* instance_parent_function_type_arguments,
    TypeArguments* instance_delayed_type_arguments,
    Bool* test_result) {
  ASSERT(array.ptr() != Object::empty_subtype_test_cache_array().ptr());
  SubtypeTestCacheTable entries(array);
  auto entry = entries[ix];
  // First get the field that determines occupancy. We have to do this with
  // load-acquire because some callers may not have the subtype test cache lock.
  *instance_class_id_or_signature =
      entry.Get<kInstanceCidOrSignature, std::memory_order_acquire>();
  // We should not be retrieving unoccupied entries.
  ASSERT(!instance_class_id_or_signature->IsNull());
  switch (num_inputs) {
    case 7:
      *destination_type = entry.Get<kDestinationType>();
      FALL_THROUGH;
    case 6:
      *instance_delayed_type_arguments =
          entry.Get<kInstanceDelayedFunctionTypeArguments>();
      FALL_THROUGH;
    case 5:
      *instance_parent_function_type_arguments =
          entry.Get<kInstanceParentFunctionTypeArguments>();
      FALL_THROUGH;
    case 4:
      *function_type_arguments = entry.Get<kFunctionTypeArguments>();
      FALL_THROUGH;
    case 3:
      *instantiator_type_arguments = entry.Get<kInstantiatorTypeArguments>();
      FALL_THROUGH;
    case 2:
      *instance_type_arguments = entry.Get<kInstanceTypeArguments>();
      FALL_THROUGH;
    case 1:
      break;
    default:
      UNREACHABLE();
  }
  *test_result = entry.Get<kTestResult>();
}

bool SubtypeTestCache::GetNextCheck(
    intptr_t* ix,
    Object* instance_class_id_or_signature,
    AbstractType* destination_type,
    TypeArguments* instance_type_arguments,
    TypeArguments* instantiator_type_arguments,
    TypeArguments* function_type_arguments,
    TypeArguments* instance_parent_function_type_arguments,
    TypeArguments* instance_delayed_type_arguments,
    Bool* test_result) const {
  ASSERT(ix != nullptr);
  for (intptr_t i = *ix; i < NumEntries(); i++) {
    ASSERT(Thread::Current()
               ->isolate_group()
               ->subtype_test_cache_mutex()
               ->IsOwnedByCurrentThread());
    if (IsOccupied(i)) {
      GetCurrentCheck(i, instance_class_id_or_signature, destination_type,
                      instance_type_arguments, instantiator_type_arguments,
                      function_type_arguments,
                      instance_parent_function_type_arguments,
                      instance_delayed_type_arguments, test_result);
      *ix = i + 1;
      return true;
    }
  }
  return false;
}

bool SubtypeTestCache::HasCheck(
    const Object& instance_class_id_or_signature,
    const AbstractType& destination_type,
    const TypeArguments& instance_type_arguments,
    const TypeArguments& instantiator_type_arguments,
    const TypeArguments& function_type_arguments,
    const TypeArguments& instance_parent_function_type_arguments,
    const TypeArguments& instance_delayed_type_arguments,
    intptr_t* index,
    Bool* result) const {
  const auto& data = Array::Handle(cache());
  auto loc = FindKeyOrUnused(
      data, num_inputs(), instance_class_id_or_signature, destination_type,
      instance_type_arguments, instantiator_type_arguments,
      function_type_arguments, instance_parent_function_type_arguments,
      instance_delayed_type_arguments);
  if (loc.present) {
    if (index != nullptr) {
      *index = loc.entry;
    }
    if (result != nullptr) {
      SubtypeTestCacheTable entries(data);
      const auto& entry = entries[loc.entry];
      // A positive result from FindKeyOrUnused means that load-acquire is not
      // needed, as an occupied entry never changes for a given backing array.
      *result = entry.Get<kTestResult>();
      ASSERT(!result->IsNull());
    }
  }
  return loc.present;
}

void SubtypeTestCache::WriteEntryToBuffer(Zone* zone,
                                          BaseTextBuffer* buffer,
                                          intptr_t index,
                                          const char* line_prefix) const {
  ASSERT(Thread::Current()
             ->isolate_group()
             ->subtype_test_cache_mutex()
             ->IsOwnedByCurrentThread());
  WriteCurrentEntryToBuffer(zone, buffer, index, line_prefix);
}

void SubtypeTestCache::WriteToBuffer(Zone* zone,
                                     BaseTextBuffer* buffer,
                                     const char* line_prefix) const {
  ASSERT(Thread::Current()
             ->isolate_group()
             ->subtype_test_cache_mutex()
             ->IsOwnedByCurrentThread());
  WriteToBufferUnlocked(zone, buffer, line_prefix);
}

void SubtypeTestCache::WriteCurrentEntryToBuffer(
    Zone* zone,
    BaseTextBuffer* buffer,
    intptr_t index,
    const char* line_prefix) const {
  const char* separator =
      line_prefix == nullptr ? ", " : OS::SCreate(zone, "\n%s", line_prefix);
  auto& instance_class_id_or_signature = Object::Handle(zone);
  auto& destination_type = AbstractType::Handle(zone);
  auto& instance_type_arguments = TypeArguments::Handle(zone);
  auto& instantiator_type_arguments = TypeArguments::Handle(zone);
  auto& function_type_arguments = TypeArguments::Handle(zone);
  auto& instance_parent_function_type_arguments = TypeArguments::Handle(zone);
  auto& instance_delayed_type_arguments = TypeArguments::Handle(zone);
  auto& result = Bool::Handle(zone);
  GetCurrentCheck(index, &instance_class_id_or_signature, &destination_type,
                  &instance_type_arguments, &instantiator_type_arguments,
                  &function_type_arguments,
                  &instance_parent_function_type_arguments,
                  &instance_delayed_type_arguments, &result);
  buffer->Printf(
      "%" Pd ": [ %#" Px ", %#" Px ", %#" Px ", %#" Px ", %#" Px ", %#" Px
      ", %#" Px ", %#" Px " ]",
      index, static_cast<uword>(instance_class_id_or_signature.ptr()),
      static_cast<uword>(instance_type_arguments.ptr()),
      static_cast<uword>(instantiator_type_arguments.ptr()),
      static_cast<uword>(function_type_arguments.ptr()),
      static_cast<uword>(instance_parent_function_type_arguments.ptr()),
      static_cast<uword>(instance_delayed_type_arguments.ptr()),
      static_cast<uword>(destination_type.ptr()),
      static_cast<uword>(result.ptr()));
  if (instance_class_id_or_signature.IsSmi()) {
    buffer->Printf("%sclass id: %" Pd "", separator,
                   Smi::Cast(instance_class_id_or_signature).Value());
  } else {
    buffer->Printf(
        "%ssignature: %s", separator,
        FunctionType::Cast(instance_class_id_or_signature).ToCString());
  }
  if (!instance_type_arguments.IsNull()) {
    if (instance_class_id_or_signature.IsSmi()) {
      buffer->Printf("%sinstance type arguments: %s", separator,
                     instance_type_arguments.ToCString());
    } else {
      ASSERT(instance_class_id_or_signature.IsFunctionType());
      buffer->Printf("%sclosure instantiator function type arguments: %s",
                     separator, instance_type_arguments.ToCString());
    }
  }
  if (!instantiator_type_arguments.IsNull()) {
    buffer->Printf("%sinstantiator type arguments: %s", separator,
                   instantiator_type_arguments.ToCString());
  }
  if (!function_type_arguments.IsNull()) {
    buffer->Printf("%sfunction type arguments: %s", separator,
                   function_type_arguments.ToCString());
  }
  if (!instance_parent_function_type_arguments.IsNull()) {
    buffer->Printf("%sclosure parent function type arguments: %s", separator,
                   instance_parent_function_type_arguments.ToCString());
  }
  if (!instance_delayed_type_arguments.IsNull()) {
    buffer->Printf("%sclosure delayed function type arguments: %s", separator,
                   instance_delayed_type_arguments.ToCString());
  }
  if (!destination_type.IsNull()) {
    buffer->Printf("%sdestination type: %s", separator,
                   destination_type.ToCString());
    if (!destination_type.IsInstantiated()) {
      AbstractType& test_type = AbstractType::Handle(
          zone, destination_type.InstantiateFrom(instantiator_type_arguments,
                                                 function_type_arguments,
                                                 kAllFree, Heap::kNew));
      const auto type_class_id = test_type.type_class_id();
      buffer->Printf("%sinstantiated type: %s", separator,
                     test_type.ToCString());
      buffer->Printf("%sinstantiated type class id: %d", separator,
                     type_class_id);
    }
  }
  buffer->Printf("%sresult: %s", separator, result.ToCString());
}

void SubtypeTestCache::WriteToBufferUnlocked(Zone* zone,
                                             BaseTextBuffer* buffer,
                                             const char* line_prefix) const {
  const char* separator =
      line_prefix == nullptr ? " " : OS::SCreate(zone, "\n%s", line_prefix);
  const char* internal_line_prefix =
      line_prefix == nullptr
          ? nullptr
          : OS::SCreate(zone, "%s%s", line_prefix, line_prefix);
  const intptr_t num_entries = NumEntries();
  buffer->Printf("SubtypeTestCache(%" Pd ", %" Pd "", num_inputs(),
                 num_occupied());
  for (intptr_t i = 0; i < num_entries; i++) {
    if (!IsOccupied(i)) continue;
    buffer->Printf(",%s{", separator);
    WriteCurrentEntryToBuffer(zone, buffer, i, internal_line_prefix);
    buffer->Printf(line_prefix != nullptr ? "}" : " }");
  }
  buffer->AddString(line_prefix != nullptr && num_entries != 0 ? "\n)" : ")");
}

void SubtypeTestCache::Reset() const {
  set_num_occupied(0);
  set_cache(Object::empty_subtype_test_cache_array());
}

bool SubtypeTestCache::Equals(const SubtypeTestCache& other) const {
  ASSERT(Thread::Current()
             ->isolate_group()
             ->subtype_test_cache_mutex()
             ->IsOwnedByCurrentThread());
  if (ptr() == other.ptr()) {
    return true;
  }
  if (num_inputs() != other.num_inputs()) return false;
  if (num_occupied() != other.num_occupied()) return false;
  return Array::Handle(cache()).Equals(Array::Handle(other.cache()));
}

SubtypeTestCachePtr SubtypeTestCache::Copy(Thread* thread) const {
  ASSERT(thread->isolate_group()
             ->subtype_test_cache_mutex()
             ->IsOwnedByCurrentThread());
  if (IsNull()) {
    return SubtypeTestCache::null();
  }
  Zone* const zone = thread->zone();
  // STC caches are only copied on write if there are not enough unoccupied
  // entries to store a new one, so we need to copy the array.
  const auto& result =
      SubtypeTestCache::Handle(zone, SubtypeTestCache::New(num_inputs()));
  auto& entry_cache = Array::Handle(zone, cache());
  entry_cache = entry_cache.Copy();
  result.set_cache(entry_cache);
  result.set_num_occupied(num_occupied());
  return result.ptr();
}

bool SubtypeTestCache::IsOccupied(intptr_t index) const {
  ASSERT(!IsNull());
  ASSERT(index < NumEntries());
  const intptr_t cache_index =
      index * kTestEntryLength + kInstanceCidOrSignature;
  NoSafepointScope no_safepoint;
  return cache()->untag()->element<std::memory_order_acquire>(cache_index) !=
         Object::null();
}

intptr_t SubtypeTestCache::UsedInputsForType(const AbstractType& type) {
  if (type.IsType()) {
    if (type.IsInstantiated()) return 2;
    if (type.IsInstantiated(kFunctions)) return 3;
    return 4;
  }
  // Default to all inputs except for the destination type, which must be
  // statically known, otherwise this method wouldn't be called.
  static_assert(kDestinationType == kMaxInputs - 1,
                "destination type is not last input");
  return kMaxInputs - 1;
}

const char* SubtypeTestCache::ToCString() const {
  auto const zone = Thread::Current()->zone();
  ZoneTextBuffer buffer(zone);
  WriteToBufferUnlocked(zone, &buffer);
  return buffer.buffer();
}

LoadingUnitPtr LoadingUnit::New(intptr_t id, const LoadingUnit& parent) {
  ASSERT(Object::loadingunit_class() != Class::null());
  // LoadingUnit objects are long living objects, allocate them in the
  // old generation.
  auto result = Object::Allocate<LoadingUnit>(Heap::kOld);
  NoSafepointScope scope;
  ASSERT(Utils::IsInt(UntaggedLoadingUnit::IdBits::bitsize(), id));
  result->untag()->packed_fields_.Update<UntaggedLoadingUnit::IdBits>(id);
  result->untag()->set_parent(parent.ptr());
  return result;
}

void LoadingUnit::set_base_objects(const Array& value) const {
  untag()->set_base_objects(value.ptr());
}

const char* LoadingUnit::ToCString() const {
  return "LoadingUnit";
}

ObjectPtr LoadingUnit::IssueLoad() const {
  set_load_outstanding();
  return Isolate::Current()->CallDeferredLoadHandler(id());
}

ObjectPtr LoadingUnit::CompleteLoad(const String& error_message,
                                    bool transient_error) const {
  set_loaded(error_message.IsNull());

  const Library& lib = Library::Handle(Library::CoreLibrary());
  const String& sel = String::Handle(String::New("_completeLoads"));
  const Function& func = Function::Handle(lib.LookupFunctionAllowPrivate(sel));
  ASSERT(!func.IsNull());
  const Array& args = Array::Handle(Array::New(3));
  args.SetAt(0, Smi::Handle(Smi::New(id())));
  args.SetAt(1, error_message);
  args.SetAt(2, Bool::Get(transient_error));
  return DartEntry::InvokeFunction(func, args);
}

// The assignment to loading units here must match that in
// AssignLoadingUnitsCodeVisitor, which runs after compilation is done.
intptr_t LoadingUnit::LoadingUnitOf(const Function& function) {
  Thread* thread = Thread::Current();
  REUSABLE_CLASS_HANDLESCOPE(thread);
  REUSABLE_LIBRARY_HANDLESCOPE(thread);
  REUSABLE_LOADING_UNIT_HANDLESCOPE(thread);

  Class& cls = thread->ClassHandle();
  Library& lib = thread->LibraryHandle();
  LoadingUnit& unit = thread->LoadingUnitHandle();

  cls = function.Owner();
  lib = cls.library();
  unit = lib.loading_unit();
  if (unit.IsNull()) {
    FATAL("Unable to find loading unit of %s (class %s, library %s)",
          function.ToFullyQualifiedCString(), cls.ToCString(), lib.ToCString());
  }
  return unit.id();
}

intptr_t LoadingUnit::LoadingUnitOf(const Code& code) {
  if (code.IsStubCode() || code.IsTypeTestStubCode() ||
      code.IsAllocationStubCode()) {
    return LoadingUnit::kRootId;
  } else {
    Thread* thread = Thread::Current();
    REUSABLE_FUNCTION_HANDLESCOPE(thread);
    REUSABLE_CLASS_HANDLESCOPE(thread);
    REUSABLE_LIBRARY_HANDLESCOPE(thread);
    REUSABLE_LOADING_UNIT_HANDLESCOPE(thread);

    Class& cls = thread->ClassHandle();
    Library& lib = thread->LibraryHandle();
    LoadingUnit& unit = thread->LoadingUnitHandle();
    Function& func = thread->FunctionHandle();

    if (code.IsFunctionCode()) {
      func ^= code.function();
      cls = func.Owner();
      lib = cls.library();
      unit = lib.loading_unit();
      ASSERT(!unit.IsNull());
      return unit.id();
    } else {
      UNREACHABLE();
      return LoadingUnit::kIllegalId;
    }
  }
}

const char* Error::ToErrorCString() const {
  if (IsNull()) {
    return "Error: null";
  }
  UNREACHABLE();
  return "Error";
}

const char* Error::ToCString() const {
  if (IsNull()) {
    return "Error: null";
  }
  // Error is an abstract class.  We should never reach here.
  UNREACHABLE();
  return "Error";
}

ApiErrorPtr ApiError::New() {
  ASSERT(Object::api_error_class() != Class::null());
  return Object::Allocate<ApiError>(Heap::kOld);
}

ApiErrorPtr ApiError::New(const String& message, Heap::Space space) {
#ifndef PRODUCT
  if (FLAG_print_stacktrace_at_api_error) {
    OS::PrintErr("ApiError: %s\n", message.ToCString());
    Profiler::DumpStackTrace(false /* for_crash */);
  }
#endif  // !PRODUCT

  ASSERT(Object::api_error_class() != Class::null());
  const auto& result = ApiError::Handle(Object::Allocate<ApiError>(space));
  result.set_message(message);
  return result.ptr();
}

void ApiError::set_message(const String& message) const {
  untag()->set_message(message.ptr());
}

const char* ApiError::ToErrorCString() const {
  const String& msg_str = String::Handle(message());
  return msg_str.ToCString();
}

const char* ApiError::ToCString() const {
  return "ApiError";
}

LanguageErrorPtr LanguageError::New() {
  ASSERT(Object::language_error_class() != Class::null());
  return Object::Allocate<LanguageError>(Heap::kOld);
}

LanguageErrorPtr LanguageError::NewFormattedV(const Error& prev_error,
                                              const Script& script,
                                              TokenPosition token_pos,
                                              bool report_after_token,
                                              Report::Kind kind,
                                              Heap::Space space,
                                              const char* format,
                                              va_list args) {
  ASSERT(Object::language_error_class() != Class::null());
  const auto& result =
      LanguageError::Handle(Object::Allocate<LanguageError>(space));
  result.set_previous_error(prev_error);
  result.set_script(script);
  result.set_token_pos(token_pos);
  result.set_report_after_token(report_after_token);
  result.set_kind(kind);
  result.set_message(
      String::Handle(String::NewFormattedV(format, args, space)));
  return result.ptr();
}

LanguageErrorPtr LanguageError::NewFormatted(const Error& prev_error,
                                             const Script& script,
                                             TokenPosition token_pos,
                                             bool report_after_token,
                                             Report::Kind kind,
                                             Heap::Space space,
                                             const char* format,
                                             ...) {
  va_list args;
  va_start(args, format);
  LanguageErrorPtr result = LanguageError::NewFormattedV(
      prev_error, script, token_pos, report_after_token, kind, space, format,
      args);
  NoSafepointScope no_safepoint;
  va_end(args);
  return result;
}

LanguageErrorPtr LanguageError::New(const String& formatted_message,
                                    Report::Kind kind,
                                    Heap::Space space) {
  ASSERT(Object::language_error_class() != Class::null());
  const auto& result =
      LanguageError::Handle(Object::Allocate<LanguageError>(space));
  result.set_formatted_message(formatted_message);
  result.set_kind(kind);
  return result.ptr();
}

void LanguageError::set_previous_error(const Error& value) const {
  untag()->set_previous_error(value.ptr());
}

void LanguageError::set_script(const Script& value) const {
  untag()->set_script(value.ptr());
}

void LanguageError::set_token_pos(TokenPosition token_pos) const {
  ASSERT(!token_pos.IsClassifying());
  StoreNonPointer(&untag()->token_pos_, token_pos);
}

void LanguageError::set_report_after_token(bool value) const {
  StoreNonPointer(&untag()->report_after_token_, value);
}

void LanguageError::set_kind(uint8_t value) const {
  StoreNonPointer(&untag()->kind_, value);
}

void LanguageError::set_message(const String& value) const {
  untag()->set_message(value.ptr());
}

void LanguageError::set_formatted_message(const String& value) const {
  untag()->set_formatted_message(value.ptr());
}

StringPtr LanguageError::FormatMessage() const {
  if (formatted_message() != String::null()) {
    return formatted_message();
  }
  String& result = String::Handle(
      Report::PrependSnippet(kind(), Script::Handle(script()), token_pos(),
                             report_after_token(), String::Handle(message())));
  // Prepend previous error message.
  const Error& prev_error = Error::Handle(previous_error());
  if (!prev_error.IsNull()) {
    result = String::Concat(
        String::Handle(String::New(prev_error.ToErrorCString())), result);
  }
  set_formatted_message(result);
  return result.ptr();
}

const char* LanguageError::ToErrorCString() const {
  const String& msg_str = String::Handle(FormatMessage());
  return msg_str.ToCString();
}

const char* LanguageError::ToCString() const {
  return "LanguageError";
}

UnhandledExceptionPtr UnhandledException::New(const Instance& exception,
                                              const Instance& stacktrace,
                                              Heap::Space space) {
  ASSERT(Object::unhandled_exception_class() != Class::null());
  const auto& result =
      UnhandledException::Handle(Object::Allocate<UnhandledException>(space));
  result.set_exception(exception);
  result.set_stacktrace(stacktrace);
  return result.ptr();
}

UnhandledExceptionPtr UnhandledException::New(Heap::Space space) {
  ASSERT(Object::unhandled_exception_class() != Class::null());
  return Object::Allocate<UnhandledException>(space);
}

void UnhandledException::set_exception(const Instance& exception) const {
  untag()->set_exception(exception.ptr());
}

void UnhandledException::set_stacktrace(const Instance& stacktrace) const {
  untag()->set_stacktrace(stacktrace.ptr());
}

const char* UnhandledException::ToErrorCString() const {
  Thread* thread = Thread::Current();
  auto isolate_group = thread->isolate_group();
  NoReloadScope no_reload_scope(thread);
  HANDLESCOPE(thread);
  Object& strtmp = Object::Handle();
  const char* exc_str;
  if (exception() == isolate_group->object_store()->out_of_memory()) {
    exc_str = "Out of Memory";
  } else if (exception() == isolate_group->object_store()->stack_overflow()) {
    exc_str = "Stack Overflow";
  } else {
    const Instance& exc = Instance::Handle(exception());
    strtmp = DartLibraryCalls::ToString(exc);
    if (!strtmp.IsError()) {
      exc_str = strtmp.ToCString();
    } else {
      exc_str = "<Received error while converting exception to string>";
    }
  }
  const Instance& stack = Instance::Handle(stacktrace());
  const char* stack_str;
  if (stack.IsNull()) {
    stack_str = "null";
  } else if (stack.IsStackTrace()) {
    stack_str = StackTrace::Cast(stack).ToCString();
  } else {
    strtmp = DartLibraryCalls::ToString(stack);
    if (!strtmp.IsError()) {
      stack_str = strtmp.ToCString();
    } else {
      stack_str = "<Received error while converting stack trace to string>";
    }
  }
  return OS::SCreate(thread->zone(), "Unhandled exception:\n%s\n%s", exc_str,
                     stack_str);
}

const char* UnhandledException::ToCString() const {
  return "UnhandledException";
}

UnwindErrorPtr UnwindError::New(const String& message, Heap::Space space) {
  ASSERT(Object::unwind_error_class() != Class::null());
  const auto& result =
      UnwindError::Handle(Object::Allocate<UnwindError>(space));
  result.set_message(message);
  ASSERT_EQUAL(result.is_user_initiated(), false);
  return result.ptr();
}

void UnwindError::set_message(const String& message) const {
  untag()->set_message(message.ptr());
}

void UnwindError::set_is_user_initiated(bool value) const {
  StoreNonPointer(&untag()->is_user_initiated_, value);
}

const char* UnwindError::ToErrorCString() const {
  const String& msg_str = String::Handle(message());
  return msg_str.ToCString();
}

const char* UnwindError::ToCString() const {
  return "UnwindError";
}

ObjectPtr Instance::InvokeGetter(const String& getter_name,
                                 bool check_is_entrypoint,
                                 bool respect_reflectable) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  Class& klass = Class::Handle(zone, clazz());
  CHECK_ERROR(klass.EnsureIsFinalized(thread));
  const auto& inst_type_args =
      klass.NumTypeArguments() > 0
          ? TypeArguments::Handle(zone, GetTypeArguments())
          : Object::null_type_arguments();

  const String& internal_getter_name =
      String::Handle(zone, Field::GetterName(getter_name));
  Function& function = Function::Handle(
      zone,
      Resolver::ResolveDynamicAnyArgs(zone, klass, internal_getter_name,
                                      /*allow_add=*/!FLAG_precompiled_mode));

  // Check for method extraction when method extractors are not lazily created.
  if (function.IsNull() && FLAG_precompiled_mode) {
    function = Resolver::ResolveDynamicAnyArgs(zone, klass, getter_name,
                                               /*allow_add=*/false);

    if (!function.IsNull() && function.SafeToClosurize()) {
      if (check_is_entrypoint) {
        CHECK_ERROR(function.VerifyEntryPoint(EntryPointPragma::kGetterOnly));
      }
      const Function& closure_function =
          Function::Handle(zone, function.ImplicitClosureFunction());
      return closure_function.ImplicitInstanceClosure(*this);
    }
  }

  const int kTypeArgsLen = 0;
  const int kNumArgs = 1;
  const Array& args = Array::Handle(zone, Array::New(kNumArgs));
  args.SetAt(0, *this);
  const Array& args_descriptor = Array::Handle(
      zone,
      ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length(), Heap::kNew));

  return InvokeInstanceFunction(thread, *this, function, internal_getter_name,
                                args, args_descriptor, check_is_entrypoint,
                                EntryPointPragma::kGetterOnly,
                                respect_reflectable, inst_type_args);
}

ObjectPtr Instance::InvokeSetter(const String& setter_name,
                                 const Instance& value,
                                 bool check_is_entrypoint,
                                 bool respect_reflectable) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  const Class& klass = Class::Handle(zone, clazz());
  CHECK_ERROR(klass.EnsureIsFinalized(thread));
  const auto& inst_type_args =
      klass.NumTypeArguments() > 0
          ? TypeArguments::Handle(zone, GetTypeArguments())
          : Object::null_type_arguments();

  const String& internal_setter_name =
      String::Handle(zone, Field::SetterName(setter_name));
  const Function& setter = Function::Handle(
      zone,
      Resolver::ResolveDynamicAnyArgs(zone, klass, internal_setter_name,
                                      /*allow_add=*/!FLAG_precompiled_mode));

  const int kTypeArgsLen = 0;
  const int kNumArgs = 2;
  const Array& args = Array::Handle(zone, Array::New(kNumArgs));
  args.SetAt(0, *this);
  args.SetAt(1, value);
  const Array& args_descriptor = Array::Handle(
      zone,
      ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length(), Heap::kNew));

  return InvokeInstanceFunction(thread, *this, setter, internal_setter_name,
                                args, args_descriptor, check_is_entrypoint,
                                EntryPointPragma::kSetterOnly,
                                respect_reflectable, inst_type_args);
}

ObjectPtr Instance::Invoke(const String& function_name,
                           const Array& args,
                           const Array& arg_names,
                           bool check_is_entrypoint,
                           bool respect_reflectable) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Class& klass = Class::Handle(zone, clazz());
  CHECK_ERROR(klass.EnsureIsFinalized(thread));

  Function& function = Function::Handle(
      zone,
      Resolver::ResolveDynamicAnyArgs(zone, klass, function_name,
                                      /*allow_add=*/!FLAG_precompiled_mode));

  // We don't pass any explicit type arguments, which will be understood as
  // using dynamic for any function type arguments by lower layers.
  const int kTypeArgsLen = 0;
  const Array& args_descriptor = Array::Handle(
      zone, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length(),
                                          arg_names, Heap::kNew));

  const auto& inst_type_args =
      klass.NumTypeArguments() > 0
          ? TypeArguments::Handle(zone, GetTypeArguments())
          : Object::null_type_arguments();

  if (function.IsNull()) {
    // Didn't find a method: try to find a getter and invoke call on its result.
    const String& getter_name =
        String::Handle(zone, Field::GetterName(function_name));
    function =
        Resolver::ResolveDynamicAnyArgs(zone, klass, getter_name,
                                        /*allow_add=*/!FLAG_precompiled_mode);
    if (!function.IsNull()) {
      ASSERT(function.kind() != UntaggedFunction::kMethodExtractor);
      // Invoke the getter.
      const int kNumArgs = 1;
      const Array& getter_args = Array::Handle(zone, Array::New(kNumArgs));
      getter_args.SetAt(0, *this);
      const Array& getter_args_descriptor = Array::Handle(
          zone, ArgumentsDescriptor::NewBoxed(
                    kTypeArgsLen, getter_args.Length(), Heap::kNew));
      const Object& getter_result = Object::Handle(
          zone, InvokeInstanceFunction(thread, *this, function, getter_name,
                                       getter_args, getter_args_descriptor,
                                       check_is_entrypoint,
                                       EntryPointPragma::kGetterOnly,
                                       respect_reflectable, inst_type_args));
      if (getter_result.IsError()) {
        return getter_result.ptr();
      }
      // Replace the closure as the receiver in the arguments list.
      args.SetAt(0, getter_result);
      return DartEntry::InvokeClosure(thread, args, args_descriptor);
    }
  }

  // Found an ordinary method.
  return InvokeInstanceFunction(thread, *this, function, function_name, args,
                                args_descriptor, check_is_entrypoint,
                                EntryPointPragma::kCallOnly,
                                respect_reflectable, inst_type_args);
}

ObjectPtr Instance::HashCode() const {
  // TODO(koda): Optimize for all builtin classes and all classes
  // that do not override hashCode.
  return DartLibraryCalls::HashCode(*this);
}

// Keep in sync with AsmIntrinsifier::Object_getHash.
IntegerPtr Instance::IdentityHashCode(Thread* thread) const {
  if (IsInteger()) return Integer::Cast(*this).ptr();
  if (IsString()) {
    return Smi::New(String::Cast(*this).Hash());
  }

#if defined(HASH_IN_OBJECT_HEADER)
  intptr_t hash = Object::GetCachedHash(ptr());
#else
  intptr_t hash = thread->heap()->GetHash(ptr());
#endif
  if (hash == 0) {
    if (IsNull()) {
      hash = kNullIdentityHash;
    } else if (IsBool()) {
      hash = Bool::Cast(*this).value() ? kTrueIdentityHash : kFalseIdentityHash;
    } else if (IsDouble()) {
      double val = Double::Cast(*this).value();
      if ((val >= kMinInt64RepresentableAsDouble) &&
          (val <= kMaxInt64RepresentableAsDouble)) {
        int64_t ival = static_cast<int64_t>(val);
        if (static_cast<double>(ival) == val) {
          return Integer::New(ival);
        }
      }

      uint64_t uval = bit_cast<uint64_t>(val);
      hash = ((uval >> 32) ^ (uval)) & kSmiMax;
    } else {
      do {
        hash = thread->random()->NextUInt32() & 0x3FFFFFFF;
      } while (hash == 0);
    }

#if defined(HASH_IN_OBJECT_HEADER)
    hash = Object::SetCachedHashIfNotSet(ptr(), hash);
#else
    hash = thread->heap()->SetHashIfNotSet(ptr(), hash);
#endif
  }
  return Smi::New(hash);
}

bool Instance::CanonicalizeEquals(const Instance& other) const {
  if (this->ptr() == other.ptr()) {
    return true;  // "===".
  }

  if (other.IsNull() || (this->clazz() != other.clazz())) {
    return false;
  }

  {
    NoSafepointScope no_safepoint;
    // Raw bits compare.
    const intptr_t instance_size = SizeFromClass();
    ASSERT(instance_size != 0);
    const intptr_t other_instance_size = other.SizeFromClass();
    ASSERT(other_instance_size != 0);
    if (instance_size != other_instance_size) {
      return false;
    }
    uword this_addr = reinterpret_cast<uword>(this->untag());
    uword other_addr = reinterpret_cast<uword>(other.untag());
    for (intptr_t offset = Instance::NextFieldOffset(); offset < instance_size;
         offset += kCompressedWordSize) {
      if ((reinterpret_cast<CompressedObjectPtr*>(this_addr + offset)
               ->Decompress(untag()->heap_base())) !=
          (reinterpret_cast<CompressedObjectPtr*>(other_addr + offset)
               ->Decompress(untag()->heap_base()))) {
        return false;
      }
    }
  }
  return true;
}

bool Symbol::IsSymbolCid(Thread* thread, classid_t class_id) {
  auto object_store = thread->isolate_group()->object_store();
  return Class::GetClassId(object_store->symbol_class()) == class_id;
}

// Must be kept in sync with Symbol.hashCode in symbol_patch.dart
uint32_t Symbol::CanonicalizeHash(Thread* thread, const Instance& instance) {
  ASSERT(IsSymbolCid(thread, instance.GetClassId()));

  auto zone = thread->zone();
  auto object_store = thread->isolate_group()->object_store();

  const auto& symbol_name_field =
      Field::Handle(zone, object_store->symbol_name_field());
  ASSERT(!symbol_name_field.IsNull());

  // Keep in sync with sdk/lib/_internal/vm/lib/symbol_patch.dart.
  const auto& name =
      String::Cast(Object::Handle(zone, instance.GetField(symbol_name_field)));
  const uint32_t arbitrary_prime = 664597;
  return 0x1fffffff & (arbitrary_prime * name.CanonicalizeHash());
}

uint32_t Instance::CanonicalizeHash() const {
  if (GetClassId() == kNullCid) {
    return kNullIdentityHash;
  }
  Thread* thread = Thread::Current();
  uint32_t hash = thread->heap()->GetCanonicalHash(ptr());
  if (hash != 0) {
    return hash;
  }
  Zone* zone = thread->zone();
  const Class& cls = Class::Handle(zone, clazz());
  const bool is_symbol = Symbol::IsSymbolCid(thread, cls.id());

  NoSafepointScope no_safepoint(thread);

  if (is_symbol) {
    hash = Symbol::CanonicalizeHash(thread, *this);
  } else {
    const intptr_t class_id = cls.id();
    ASSERT(class_id != 0);
    hash = class_id;
    uword this_addr = reinterpret_cast<uword>(this->untag());
    Object& obj = Object::Handle(zone);
    Instance& instance = Instance::Handle(zone);

    const auto unboxed_fields_bitmap =
        thread->isolate_group()->class_table()->GetUnboxedFieldsMapAt(
            GetClassId());

    for (intptr_t offset = Instance::NextFieldOffset();
         offset < cls.host_next_field_offset(); offset += kCompressedWordSize) {
      if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
        if (kCompressedWordSize == 8) {
          hash = CombineHashes(
              hash, *reinterpret_cast<uint32_t*>(this_addr + offset));
          hash = CombineHashes(
              hash, *reinterpret_cast<uint32_t*>(this_addr + offset + 4));
        } else {
          hash = CombineHashes(
              hash, *reinterpret_cast<uint32_t*>(this_addr + offset));
        }
      } else {
        obj = reinterpret_cast<CompressedObjectPtr*>(this_addr + offset)
                  ->Decompress(untag()->heap_base());
        if (obj.IsSentinel()) {
          hash = CombineHashes(hash, 11);
        } else {
          instance ^= obj.ptr();
          hash = CombineHashes(hash, instance.CanonicalizeHash());
        }
      }
    }
    hash = FinalizeHash(hash, String::kHashBits);
  }
  thread->heap()->SetCanonicalHash(ptr(), hash);
  return hash;
}

#if defined(DEBUG)
class CheckForPointers : public ObjectPointerVisitor {
 public:
  explicit CheckForPointers(IsolateGroup* isolate_group)
      : ObjectPointerVisitor(isolate_group), has_pointers_(false) {}

  bool has_pointers() const { return has_pointers_; }

  void VisitPointers(ObjectPtr* first, ObjectPtr* last) override {
    if (last >= first) {
      has_pointers_ = true;
    }
  }

#if defined(DART_COMPRESSED_POINTERS)
  void VisitCompressedPointers(uword heap_base,
                               CompressedObjectPtr* first,
                               CompressedObjectPtr* last) override {
    if (last >= first) {
      has_pointers_ = true;
    }
  }
#endif

 private:
  bool has_pointers_;

  DISALLOW_COPY_AND_ASSIGN(CheckForPointers);
};
#endif  // DEBUG

void Instance::CanonicalizeFieldsLocked(Thread* thread) const {
  const intptr_t class_id = GetClassId();
  if (class_id >= kNumPredefinedCids) {
    // Iterate over all fields, canonicalize numbers and strings, expect all
    // other instances to be canonical otherwise report error (return false).
    Zone* zone = thread->zone();
    Object& obj = Object::Handle(zone);
    const intptr_t instance_size = SizeFromClass();
    ASSERT(instance_size != 0);
    const auto unboxed_fields_bitmap =
        thread->isolate_group()->class_table()->GetUnboxedFieldsMapAt(class_id);
    for (intptr_t offset = Instance::NextFieldOffset(); offset < instance_size;
         offset += kCompressedWordSize) {
      if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
        continue;
      }
      obj = this->FieldAddrAtOffset(offset)->Decompress(untag()->heap_base());
      if (obj.IsInstance()) {
        obj = Instance::Cast(obj).CanonicalizeLocked(thread);
        this->SetFieldAtOffset(offset, obj);
      } else {
        ASSERT(obj.IsNull() || obj.IsSentinel());
      }
    }
  } else {
#if defined(DEBUG) && !defined(DART_COMPRESSED_POINTERS)
    // Make sure that we are not missing any fields.
    IsolateGroup* group = IsolateGroup::Current();
    CheckForPointers has_pointers(group);
    this->ptr()->untag()->VisitPointersPrecise(&has_pointers);
    ASSERT(!has_pointers.has_pointers());
#endif  // DEBUG
  }
}

InstancePtr Instance::CopyShallowToOldSpace(Thread* thread) const {
  return Instance::RawCast(Object::Clone(*this, Heap::kOld));
}

InstancePtr Instance::Canonicalize(Thread* thread) const {
  SafepointMutexLocker ml(
      thread->isolate_group()->constant_canonicalization_mutex());
  return CanonicalizeLocked(thread);
}

InstancePtr Instance::CanonicalizeLocked(Thread* thread) const {
  if (!this->ptr()->IsHeapObject() || this->IsCanonical()) {
    return this->ptr();
  }
  ASSERT(!IsNull());
  CanonicalizeFieldsLocked(thread);
  Zone* zone = thread->zone();
  const Class& cls = Class::Handle(zone, this->clazz());
  Instance& result =
      Instance::Handle(zone, cls.LookupCanonicalInstance(zone, *this));
  if (!result.IsNull()) {
    return result.ptr();
  }
  if (IsNew()) {
    ASSERT((thread->isolate() == Dart::vm_isolate()) || !InVMIsolateHeap());
    // Create a canonical object in old space.
    result ^= Object::Clone(*this, Heap::kOld);
  } else {
    result = this->ptr();
  }
  ASSERT(result.IsOld());
  result.SetCanonical();
  return cls.InsertCanonicalConstant(zone, result);
}

ObjectPtr Instance::GetField(const Field& field) const {
  if (field.is_unboxed()) {
    switch (field.guarded_cid()) {
      case kDoubleCid:
        return Double::New(*reinterpret_cast<double_t*>(FieldAddr(field)));
      case kFloat32x4Cid:
        return Float32x4::New(
            *reinterpret_cast<simd128_value_t*>(FieldAddr(field)));
      case kFloat64x2Cid:
        return Float64x2::New(
            *reinterpret_cast<simd128_value_t*>(FieldAddr(field)));
      default:
        return Integer::New(*reinterpret_cast<int64_t*>(FieldAddr(field)));
    }
  } else {
    return FieldAddr(field)->Decompress(untag()->heap_base());
  }
}

void Instance::SetField(const Field& field, const Object& value) const {
  if (field.is_unboxed()) {
    switch (field.guarded_cid()) {
      case kDoubleCid:
        StoreNonPointer(reinterpret_cast<double_t*>(FieldAddr(field)),
                        Double::Cast(value).value());
        break;
      case kFloat32x4Cid:
        StoreNonPointer(reinterpret_cast<simd128_value_t*>(FieldAddr(field)),
                        Float32x4::Cast(value).value());
        break;
      case kFloat64x2Cid:
        StoreNonPointer(reinterpret_cast<simd128_value_t*>(FieldAddr(field)),
                        Float64x2::Cast(value).value());
        break;
      default:
        StoreNonPointer(reinterpret_cast<int64_t*>(FieldAddr(field)),
                        Integer::Cast(value).Value());
        break;
    }
  } else {
    field.RecordStore(value);
    StoreCompressedPointer(FieldAddr(field), value.ptr());
  }
}

void Instance::SetFieldWithoutFieldGuard(const Field& field,
                                         const Object& value) const {
  if (field.is_unboxed()) {
    switch (field.guarded_cid()) {
      case kDoubleCid:
        StoreNonPointer(reinterpret_cast<double_t*>(FieldAddr(field)),
                        Double::Cast(value).value());
        break;
      case kFloat32x4Cid:
        StoreNonPointer(reinterpret_cast<simd128_value_t*>(FieldAddr(field)),
                        Float32x4::Cast(value).value());
        break;
      case kFloat64x2Cid:
        StoreNonPointer(reinterpret_cast<simd128_value_t*>(FieldAddr(field)),
                        Float64x2::Cast(value).value());
        break;
      default:
        StoreNonPointer(reinterpret_cast<int64_t*>(FieldAddr(field)),
                        Integer::Cast(value).Value());
        break;
    }
  } else {
    // Some basic validation that we are not violating guarded cid.
    RELEASE_ASSERT(!Thread::Current()->isolate_group()->use_field_guards() ||
                   field.guarded_cid() == kDynamicCid ||
                   field.guarded_cid() == value.GetClassId() ||
                   (field.is_nullable() && value.IsNull()));
    StoreCompressedPointer(FieldAddr(field), value.ptr());
  }
}

AbstractTypePtr Instance::GetType(Heap::Space space,
                                  TypeVisibility visibility) const {
  if (IsNull()) {
    return Type::NullType();
  }
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  if (visibility == TypeVisibility::kUserVisibleType) {
    // VM hides certain internal implementation classes
    // and substitutes them with public user-visible types
    // (String, int, double, Type, List).
    if (IsString()) {
      return Type::StringType();
    } else if (IsInteger()) {
      return Type::IntType();
    } else if (IsDouble()) {
      return Type::Double();
    } else if (IsAbstractType()) {
      return Type::DartTypeType();
    } else if (IsArrayClassId(GetClassId())) {
      const auto& cls = Class::Handle(
          zone, thread->isolate_group()->object_store()->list_class());
      auto& type_arguments = TypeArguments::Handle(zone, GetTypeArguments());
      type_arguments = type_arguments.FromInstanceTypeArguments(thread, cls);
      // Assume internal VM types are properly encapsulated in the core
      // libraries and cannot appear in type arguments.
      const auto& type =
          Type::Handle(zone, Type::New(cls, type_arguments,
                                       Nullability::kNonNullable, Heap::kNew));
      type.SetIsFinalized();
      return type.Canonicalize(thread);
    }
  }
  const Class& cls = Class::Handle(zone, clazz());
  if (!cls.is_finalized()) {
    // Various predefined classes can be instantiated by the VM or
    // Dart_NewString/Integer/TypedData/... before the class is finalized.
    ASSERT(cls.is_prefinalized());
    cls.EnsureDeclarationLoaded();
  }
  if (cls.IsClosureClass()) {
    FunctionType& signature = FunctionType::Handle(
        zone, Closure::Cast(*this).GetInstantiatedSignature(zone));
    if (!signature.IsFinalized()) {
      signature.SetIsFinalized();
    }
    signature ^= signature.Canonicalize(thread);
    return signature.ptr();
  }
  if (IsRecord()) {
    ASSERT(cls.IsRecordClass());
    auto& record_type =
        RecordType::Handle(zone, Record::Cast(*this).GetRecordType(visibility));
    ASSERT(record_type.IsFinalized());
    ASSERT(record_type.IsCanonical());
    return record_type.ptr();
  }
  Type& type = Type::Handle(zone);
  if (!cls.IsGeneric()) {
    type = cls.DeclarationType();
  }
  if (type.IsNull()) {
    TypeArguments& type_arguments = TypeArguments::Handle(zone);
    const intptr_t num_type_arguments = cls.NumTypeArguments();
    if (num_type_arguments > 0) {
      type_arguments = GetTypeArguments();
      if (!type_arguments.IsNull()) {
        type_arguments = type_arguments.FromInstanceTypeArguments(thread, cls);
      }
    }
    type = Type::New(cls, type_arguments, Nullability::kNonNullable, space);
    type.SetIsFinalized();
    type ^= type.Canonicalize(thread);
  }
  return type.ptr();
}

TypeArgumentsPtr Instance::GetTypeArguments() const {
  ASSERT(!IsType());
  const Class& cls = Class::Handle(clazz());
  intptr_t field_offset = cls.host_type_arguments_field_offset();
  ASSERT(field_offset != Class::kNoTypeArguments);
  TypeArguments& type_arguments = TypeArguments::Handle();
  type_arguments ^=
      FieldAddrAtOffset(field_offset)->Decompress(untag()->heap_base());
  return type_arguments.ptr();
}

void Instance::SetTypeArguments(const TypeArguments& value) const {
  ASSERT(!IsType());
  ASSERT(value.IsNull() || value.IsCanonical());
  const Class& cls = Class::Handle(clazz());
  intptr_t field_offset = cls.host_type_arguments_field_offset();
  ASSERT(field_offset != Class::kNoTypeArguments);
  SetFieldAtOffset(field_offset, value);
}

bool Instance::IsInstanceOf(
    const AbstractType& other,
    const TypeArguments& other_instantiator_type_arguments,
    const TypeArguments& other_function_type_arguments) const {
  ASSERT(!other.IsDynamicType());
  return RuntimeTypeIsSubtypeOf(other, other_instantiator_type_arguments,
                                other_function_type_arguments);
}

// Must be kept in sync with GenerateNullIsAssignableToType in
// stub_code_compiler.cc if any changes are made.
bool Instance::NullIsAssignableTo(const AbstractType& other) {
  // "Left Null" rule: null is assignable when destination type is
  // nullable. Otherwise it is not assignable or we cannot tell
  // without instantiating type parameter.
  if (other.IsNullable()) {
    return true;
  }
  if (other.IsFutureOrType()) {
    return NullIsAssignableTo(AbstractType::Handle(other.UnwrapFutureOr()));
  }
  // Since the TAVs are not available, for non-nullable type parameters
  // this returns a conservative approximation of "not assignable" .
  return false;
}

// Must be kept in sync with GenerateNullIsAssignableToType in
// stub_code_compiler.cc if any changes are made.
bool Instance::NullIsAssignableTo(
    const AbstractType& other,
    const TypeArguments& other_instantiator_type_arguments,
    const TypeArguments& other_function_type_arguments) {
  // Do checks that don't require instantiation first.
  if (NullIsAssignableTo(other)) return true;
  if (!other.IsTypeParameter()) return false;
  const auto& type = AbstractType::Handle(other.InstantiateFrom(
      other_instantiator_type_arguments, other_function_type_arguments,
      kAllFree, Heap::kNew));
  return NullIsAssignableTo(type);
}

bool Instance::RuntimeTypeIsSubtypeOf(
    const AbstractType& other,
    const TypeArguments& other_instantiator_type_arguments,
    const TypeArguments& other_function_type_arguments) const {
  ASSERT(other.IsFinalized());
  ASSERT(ptr() != Object::sentinel().ptr());
  // Instance may not have runtimeType dynamic, void, or Never.
  if (other.IsTopTypeForSubtyping()) {
    return true;
  }
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const Class& cls = Class::Handle(zone, clazz());
  if (cls.IsClosureClass()) {
    if (other.IsDartFunctionType() || other.IsDartClosureType() ||
        other.IsObjectType()) {
      return true;
    }
    AbstractType& instantiated_other = AbstractType::Handle(zone, other.ptr());
    if (!other.IsInstantiated()) {
      instantiated_other = other.InstantiateFrom(
          other_instantiator_type_arguments, other_function_type_arguments,
          kAllFree, Heap::kOld);
      if (instantiated_other.IsTopTypeForSubtyping() ||
          instantiated_other.IsObjectType() ||
          instantiated_other.IsDartFunctionType()) {
        return true;
      }
    }
    if (RuntimeTypeIsSubtypeOfFutureOr(zone, instantiated_other)) {
      return true;
    }
    if (!instantiated_other.IsFunctionType()) {
      return false;
    }
    const FunctionType& sig = FunctionType::Handle(
        Closure::Cast(*this).GetInstantiatedSignature(zone));
    return sig.IsSubtypeOf(FunctionType::Cast(instantiated_other), Heap::kOld);
  }
  if (cls.IsRecordClass()) {
    if (other.IsDartRecordType() || other.IsObjectType()) {
      return true;
    }
    AbstractType& instantiated_other = AbstractType::Handle(zone, other.ptr());
    if (!other.IsInstantiated()) {
      instantiated_other = other.InstantiateFrom(
          other_instantiator_type_arguments, other_function_type_arguments,
          kAllFree, Heap::kOld);
      if (instantiated_other.IsTopTypeForSubtyping() ||
          instantiated_other.IsObjectType() ||
          instantiated_other.IsDartRecordType()) {
        return true;
      }
    }
    if (RuntimeTypeIsSubtypeOfFutureOr(zone, instantiated_other)) {
      return true;
    }
    if (!instantiated_other.IsRecordType()) {
      return false;
    }
    const Record& record = Record::Cast(*this);
    const RecordType& record_type = RecordType::Cast(instantiated_other);
    if (record.shape() != record_type.shape()) {
      return false;
    }
    Instance& field_value = Instance::Handle(zone);
    AbstractType& field_type = AbstractType::Handle(zone);
    const intptr_t num_fields = record.num_fields();
    for (intptr_t i = 0; i < num_fields; ++i) {
      field_value ^= record.FieldAt(i);
      field_type = record_type.FieldTypeAt(i);
      if (!field_value.RuntimeTypeIsSubtypeOf(field_type,
                                              Object::null_type_arguments(),
                                              Object::null_type_arguments())) {
        return false;
      }
    }
    return true;
  }
  TypeArguments& type_arguments = TypeArguments::Handle(zone);
  const intptr_t num_type_arguments = cls.NumTypeArguments();
  if (num_type_arguments > 0) {
    type_arguments = GetTypeArguments();
    ASSERT(type_arguments.IsNull() || type_arguments.IsCanonical());
    // The number of type arguments in the instance must be greater or equal to
    // the number of type arguments expected by the instance class.
    // A discrepancy is allowed for closures, which borrow the type argument
    // vector of their instantiator, which may be of a subclass of the class
    // defining the closure. Truncating the vector to the correct length on
    // instantiation is unnecessary. The vector may therefore be longer.
    // Also, an optimization reuses the type argument vector of the instantiator
    // of generic instances when its layout is compatible.
    ASSERT(type_arguments.IsNull() ||
           (type_arguments.Length() >= num_type_arguments));
  }
  AbstractType& instantiated_other = AbstractType::Handle(zone, other.ptr());
  if (!other.IsInstantiated()) {
    instantiated_other = other.InstantiateFrom(
        other_instantiator_type_arguments, other_function_type_arguments,
        kAllFree, Heap::kOld);
    if (instantiated_other.IsTopTypeForSubtyping()) {
      return true;
    }
  }
  if (IsNull()) {
    if (instantiated_other.IsNullType()) {
      return true;
    }
    if (RuntimeTypeIsSubtypeOfFutureOr(zone, instantiated_other)) {
      return true;
    }
    // At this point, instantiated_other can be a function type.
    return !instantiated_other.IsNonNullable();
  }
  if (!instantiated_other.IsType()) {
    return false;
  }
  // RuntimeType of non-null instance is non-nullable, so there is no need to
  // check nullability of other type.
  return Class::IsSubtypeOf(cls, type_arguments, Nullability::kNonNullable,
                            instantiated_other, Heap::kOld);
}

bool Instance::RuntimeTypeIsSubtypeOfFutureOr(Zone* zone,
                                              const AbstractType& other) const {
  if (other.IsFutureOrType()) {
    const TypeArguments& other_type_arguments =
        TypeArguments::Handle(zone, other.arguments());
    const AbstractType& other_type_arg =
        AbstractType::Handle(zone, other_type_arguments.TypeAtNullSafe(0));
    if (other_type_arg.IsTopTypeForSubtyping()) {
      return true;
    }
    if (Class::Handle(zone, clazz()).IsFutureClass()) {
      const TypeArguments& type_arguments =
          TypeArguments::Handle(zone, GetTypeArguments());
      const AbstractType& type_arg =
          AbstractType::Handle(zone, type_arguments.TypeAtNullSafe(0));
      if (type_arg.IsSubtypeOf(other_type_arg, Heap::kOld)) {
        return true;
      }
    }
    // Retry RuntimeTypeIsSubtypeOf after unwrapping type arg of FutureOr.
    if (RuntimeTypeIsSubtypeOf(other_type_arg, Object::null_type_arguments(),
                               Object::null_type_arguments())) {
      return true;
    }
  }
  return false;
}

bool Instance::OperatorEquals(const Instance& other) const {
  // TODO(koda): Optimize for all builtin classes and all classes
  // that do not override operator==.
  return DartLibraryCalls::Equals(*this, other) == Object::bool_true().ptr();
}

bool Instance::IsIdenticalTo(const Instance& other) const {
  if (ptr() == other.ptr()) return true;
  if (IsInteger() && other.IsInteger()) {
    return Integer::Cast(*this).Equals(other);
  }
  if (IsDouble() && other.IsDouble()) {
    double other_value = Double::Cast(other).value();
    return Double::Cast(*this).BitwiseEqualsToDouble(other_value);
  }
  return false;
}

intptr_t* Instance::NativeFieldsDataAddr() const {
  ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0);
  TypedDataPtr native_fields = static_cast<TypedDataPtr>(
      NativeFieldsAddr()->Decompress(untag()->heap_base()));
  if (native_fields == TypedData::null()) {
    return nullptr;
  }
  return reinterpret_cast<intptr_t*>(native_fields->untag()->data());
}

void Instance::SetNativeField(int index, intptr_t value) const {
  ASSERT(IsValidNativeIndex(index));
  Object& native_fields =
      Object::Handle(NativeFieldsAddr()->Decompress(untag()->heap_base()));
  if (native_fields.IsNull()) {
    // Allocate backing storage for the native fields.
    native_fields = TypedData::New(kIntPtrCid, NumNativeFields());
    StoreCompressedPointer(NativeFieldsAddr(), native_fields.ptr());
  }
  intptr_t byte_offset = index * sizeof(intptr_t);
  TypedData::Cast(native_fields).SetIntPtr(byte_offset, value);
}

void Instance::SetNativeFields(uint16_t num_native_fields,
                               const intptr_t* field_values) const {
  ASSERT(num_native_fields == NumNativeFields());
  ASSERT(field_values != nullptr);
  Object& native_fields =
      Object::Handle(NativeFieldsAddr()->Decompress(untag()->heap_base()));
  if (native_fields.IsNull()) {
    // Allocate backing storage for the native fields.
    native_fields = TypedData::New(kIntPtrCid, NumNativeFields());
    StoreCompressedPointer(NativeFieldsAddr(), native_fields.ptr());
  }
  for (uint16_t i = 0; i < num_native_fields; i++) {
    intptr_t byte_offset = i * sizeof(intptr_t);
    TypedData::Cast(native_fields).SetIntPtr(byte_offset, field_values[i]);
  }
}

bool Instance::IsCallable(Function* function) const {
  Class& cls = Class::Handle(clazz());
  if (cls.IsClosureClass()) {
    if (function != nullptr) {
      *function = Closure::Cast(*this).function();
    }
    return true;
  }
  // Try to resolve a "call" method.
  Zone* zone = Thread::Current()->zone();
  Function& call_function = Function::Handle(
      zone, Resolver::ResolveDynamicAnyArgs(zone, cls, Symbols::DynamicCall(),
                                            /*allow_add=*/false));
  if (call_function.IsNull()) {
    return false;
  }
  if (function != nullptr) {
    *function = call_function.ptr();
  }
  return true;
}

InstancePtr Instance::New(const Class& cls, Heap::Space space) {
  Thread* thread = Thread::Current();
  if (cls.EnsureIsAllocateFinalized(thread) != Error::null()) {
    return Instance::null();
  }
  return NewAlreadyFinalized(cls, space);
}

InstancePtr Instance::NewAlreadyFinalized(const Class& cls, Heap::Space space) {
  ASSERT(cls.is_allocate_finalized());
  intptr_t instance_size = cls.host_instance_size();
  ASSERT(instance_size > 0);
  // Initialize everything after the object header with Object::null(), since
  // this isn't a predefined class.
  const uword ptr_field_end_offset =
      instance_size - (Instance::ContainsCompressedPointers()
                           ? kCompressedWordSize
                           : kWordSize);
  return static_cast<InstancePtr>(Object::Allocate(
      cls.id(), instance_size, space, Instance::ContainsCompressedPointers(),
      from_offset<Instance>(), ptr_field_end_offset));
}

bool Instance::IsValidFieldOffset(intptr_t offset) const {
  Thread* thread = Thread::Current();
  REUSABLE_CLASS_HANDLESCOPE(thread);
  Class& cls = thread->ClassHandle();
  cls = clazz();
  return (offset >= 0 &&
          offset <= (cls.host_instance_size() - kCompressedWordSize));
}

intptr_t Instance::ElementSizeFor(intptr_t cid) {
  if (IsExternalTypedDataClassId(cid) || IsTypedDataClassId(cid) ||
      IsTypedDataViewClassId(cid) || IsUnmodifiableTypedDataViewClassId(cid)) {
    return TypedDataBase::ElementSizeInBytes(cid);
  }
  switch (cid) {
    case kArrayCid:
    case kImmutableArrayCid:
      return Array::kBytesPerElement;
    case kTypeArgumentsCid:
      return TypeArguments::ArrayTraits::kElementSize;
    case kOneByteStringCid:
      return OneByteString::kBytesPerElement;
    case kTwoByteStringCid:
      return TwoByteString::kBytesPerElement;
    default:
      UNIMPLEMENTED();
      return 0;
  }
}

intptr_t Instance::DataOffsetFor(intptr_t cid) {
  if (IsExternalTypedDataClassId(cid)) {
    // Elements start at offset 0 of the external data.
    return 0;
  }
  if (IsTypedDataClassId(cid)) {
    return TypedData::payload_offset();
  }
  switch (cid) {
    case kArrayCid:
    case kImmutableArrayCid:
      return Array::data_offset();
    case kTypeArgumentsCid:
      return TypeArguments::types_offset();
    case kOneByteStringCid:
      return OneByteString::data_offset();
    case kTwoByteStringCid:
      return TwoByteString::data_offset();
    case kRecordCid:
      return Record::field_offset(0);
    default:
      UNIMPLEMENTED();
      return Array::data_offset();
  }
}

const char* Instance::ToCString() const {
  if (IsNull()) {
    return "null";
  } else if (Thread::Current()->no_safepoint_scope_depth() > 0) {
    // Can occur when running disassembler.
    return "Instance";
  } else {
    if (IsClosure()) {
      return Closure::Cast(*this).ToCString();
    }
    // Background compiler disassembly of instructions referring to pool objects
    // calls this function and requires allocation of Type in old space.
    const AbstractType& type = AbstractType::Handle(
        GetType(Heap::kOld, TypeVisibility::kUserVisibleType));
    const String& type_name = String::Handle(type.UserVisibleName());
    return OS::SCreate(Thread::Current()->zone(), "Instance of '%s'",
                       type_name.ToCString());
  }
}

classid_t AbstractType::type_class_id() const {
  // All subclasses should implement this appropriately, so the only value that
  // should reach this implementation should be the null value.
  ASSERT(IsNull());
  // AbstractType is an abstract class.
  UNREACHABLE();
  return kIllegalCid;
}

ClassPtr AbstractType::type_class() const {
  // All subclasses should implement this appropriately, so the only value that
  // should reach this implementation should be the null value.
  ASSERT(IsNull());
  // AbstractType is an abstract class.
  UNREACHABLE();
  return Class::null();
}

TypeArgumentsPtr AbstractType::arguments() const {
  // All subclasses should implement this appropriately, so the only value that
  // should reach this implementation should be the null value.
  ASSERT(IsNull());
  // AbstractType is an abstract class.
  UNREACHABLE();
  return nullptr;
}

bool AbstractType::IsStrictlyNonNullable() const {
  // Null can be assigned to legacy and nullable types.
  if (!IsNonNullable()) {
    return false;
  }

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

  if (IsTypeParameter()) {
    const auto& bound =
        AbstractType::Handle(zone, TypeParameter::Cast(*this).bound());
    ASSERT(!bound.IsNull());
    return bound.IsStrictlyNonNullable();
  }
  if (IsFutureOrType()) {
    return AbstractType::Handle(zone, UnwrapFutureOr()).IsStrictlyNonNullable();
  }
  return true;
}

AbstractTypePtr AbstractType::SetInstantiatedNullability(
    const TypeParameter& type_param,
    Heap::Space space) const {
  Nullability result_nullability;
  const Nullability arg_nullability = nullability();
  const Nullability var_nullability = type_param.nullability();
  // Adjust nullability of result 'arg' instantiated from 'var'.
  // arg/var ! ?
  //  !      ! ?
  //  ?      ? ?
  if (var_nullability == Nullability::kNullable) {
    result_nullability = Nullability::kNullable;
  } else {
    // Keep arg nullability.
    return ptr();
  }
  if (arg_nullability == result_nullability) {
    return ptr();
  }
  if (IsType()) {
    return Type::Cast(*this).ToNullability(result_nullability, space);
  }
  if (IsFunctionType()) {
    return FunctionType::Cast(*this).ToNullability(result_nullability, space);
  }
  if (IsRecordType()) {
    return RecordType::Cast(*this).ToNullability(result_nullability, space);
  }
  if (IsTypeParameter()) {
    return TypeParameter::Cast(*this).ToNullability(result_nullability, space);
  }
  UNREACHABLE();
}

AbstractTypePtr AbstractType::NormalizeFutureOrType(Heap::Space space) const {
  if (IsFutureOrType()) {
    Zone* zone = Thread::Current()->zone();
    const AbstractType& unwrapped_type =
        AbstractType::Handle(zone, UnwrapFutureOr());
    const classid_t cid = unwrapped_type.type_class_id();
    if (cid == kDynamicCid || cid == kVoidCid) {
      return unwrapped_type.ptr();
    }
    if (cid == kInstanceCid) {
      if (IsNonNullable()) {
        return unwrapped_type.ptr();
      }
      ASSERT(IsNullable());
      return Type::Cast(unwrapped_type)
          .ToNullability(Nullability::kNullable, space);
    }
    if (cid == kNeverCid && unwrapped_type.IsNonNullable()) {
      ObjectStore* object_store = IsolateGroup::Current()->object_store();
      const Type& future_never_type =
          Type::Handle(zone, object_store->non_nullable_future_never_type());
      ASSERT(!future_never_type.IsNull());
      return future_never_type.ToNullability(nullability(), space);
    }
    if (cid == kNullCid) {
      ObjectStore* object_store = IsolateGroup::Current()->object_store();
      ASSERT(object_store->nullable_future_null_type() != Type::null());
      return object_store->nullable_future_null_type();
    }
    if (IsNullable() && unwrapped_type.IsNullable()) {
      return Type::Cast(*this).ToNullability(Nullability::kNonNullable, space);
    }
  }
  return ptr();
}

bool AbstractType::IsInstantiated(Genericity genericity,
                                  intptr_t num_free_fun_type_params) const {
  // All subclasses should implement this appropriately, so the only value that
  // should reach this implementation should be the null value.
  ASSERT(IsNull());
  // AbstractType is an abstract class.
  UNREACHABLE();
  return false;
}

void AbstractType::SetIsFinalized() const {
  ASSERT(!IsFinalized());
  set_type_state(IsInstantiated()
                     ? UntaggedAbstractType::kFinalizedInstantiated
                     : UntaggedAbstractType::kFinalizedUninstantiated);
}

void AbstractType::set_flags(uint32_t value) const {
  untag()->set_flags(value);
}

void AbstractType::set_type_state(UntaggedAbstractType::TypeState value) const {
  ASSERT(!IsCanonical());
  set_flags(
      UntaggedAbstractType::TypeStateBits::update(value, untag()->flags()));
}

void AbstractType::set_nullability(Nullability value) const {
  ASSERT(!IsCanonical());
  set_flags(UntaggedAbstractType::NullabilityBit::update(
      static_cast<uint8_t>(value), untag()->flags()));
}

bool AbstractType::IsEquivalent(
    const Instance& other,
    TypeEquality kind,
    FunctionTypeMapping* function_type_equivalence) const {
  // All subclasses should implement this appropriately, so the only value that
  // should reach this implementation should be the null value.
  ASSERT(IsNull());
  // AbstractType is an abstract class.
  UNREACHABLE();
  return false;
}

bool AbstractType::IsNullabilityEquivalent(Thread* thread,
                                           const AbstractType& other_type,
                                           TypeEquality kind) const {
  Nullability this_type_nullability = nullability();
  Nullability other_type_nullability = other_type.nullability();
  if (kind == TypeEquality::kInSubtypeTest) {
    if (this_type_nullability == Nullability::kNullable &&
        other_type_nullability == Nullability::kNonNullable) {
      return false;
    }
  } else {
    ASSERT((kind == TypeEquality::kSyntactical) ||
           (kind == TypeEquality::kCanonical));
    if (this_type_nullability != other_type_nullability) {
      return false;
    }
  }
  return true;
}

AbstractTypePtr AbstractType::InstantiateFrom(
    const TypeArguments& instantiator_type_arguments,
    const TypeArguments& function_type_arguments,
    intptr_t num_free_fun_type_params,
    Heap::Space space,
    FunctionTypeMapping* function_type_mapping,
    intptr_t num_parent_type_args_adjustment) const {
  // All subclasses should implement this appropriately, so the only value that
  // should reach this implementation should be the null value.
  ASSERT(IsNull());
  // AbstractType is an abstract class.
  UNREACHABLE();
  return nullptr;
}

AbstractTypePtr AbstractType::UpdateFunctionTypes(
    intptr_t num_parent_type_args_adjustment,
    intptr_t num_free_fun_type_params,
    Heap::Space space,
    FunctionTypeMapping* function_type_mapping) const {
  UNREACHABLE();
  return nullptr;
}

AbstractTypePtr AbstractType::Canonicalize(Thread* thread) const {
  // All subclasses should implement this appropriately, so the only value that
  // should reach this implementation should be the null value.
  ASSERT(IsNull());
  // AbstractType is an abstract class.
  UNREACHABLE();
  return nullptr;
}

void AbstractType::EnumerateURIs(URIs* uris) const {
  // All subclasses should implement this appropriately, so the only value that
  // should reach this implementation should be the null value.
  ASSERT(IsNull());
  // AbstractType is an abstract class.
  UNREACHABLE();
}

void AbstractType::AddURI(URIs* uris, const String& name, const String& uri) {
  ASSERT(uris != nullptr);
  const intptr_t len = uris->length();
  ASSERT((len % 3) == 0);
  bool print_uri = false;
  for (intptr_t i = 0; i < len; i += 3) {
    if (uris->At(i).Equals(name)) {
      if (uris->At(i + 1).Equals(uri)) {
        // Same name and same URI: no need to add this already listed URI.
        return;  // No state change is possible.
      } else {
        // Same name and different URI: the name is ambiguous, print both URIs.
        print_uri = true;
        uris->SetAt(i + 2, Symbols::print());
      }
    }
  }
  uris->Add(name);
  uris->Add(uri);
  if (print_uri) {
    uris->Add(Symbols::print());
  } else {
    uris->Add(Symbols::Empty());
  }
}

StringPtr AbstractType::PrintURIs(URIs* uris) {
  ASSERT(uris != nullptr);
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const intptr_t len = uris->length();
  ASSERT((len % 3) == 0);
  GrowableHandlePtrArray<const String> pieces(zone, 5 * (len / 3));
  for (intptr_t i = 0; i < len; i += 3) {
    // Only print URIs that have been marked.
    if (uris->At(i + 2).ptr() == Symbols::print().ptr()) {
      pieces.Add(Symbols::TwoSpaces());
      pieces.Add(uris->At(i));
      pieces.Add(Symbols::SpaceIsFromSpace());
      pieces.Add(uris->At(i + 1));
      pieces.Add(Symbols::NewLine());
    }
  }
  return Symbols::FromConcatAll(thread, pieces);
}

const char* AbstractType::NullabilitySuffix(
    NameVisibility name_visibility) const {
  if (IsDynamicType() || IsVoidType() || IsNullType()) {
    // Hide nullable suffix.
    return "";
  }
  // Keep in sync with Nullability enum in runtime/vm/object.h.
  switch (nullability()) {
    case Nullability::kNullable:
      return "?";
    case Nullability::kNonNullable:
      return "";
    default:
      UNREACHABLE();
  }
}

StringPtr AbstractType::Name() const {
  return Symbols::New(Thread::Current(), NameCString());
}

const char* AbstractType::NameCString() const {
  Thread* thread = Thread::Current();
  ZoneTextBuffer printer(thread->zone());
  PrintName(kInternalName, &printer);
  return printer.buffer();
}

StringPtr AbstractType::UserVisibleName() const {
  return Symbols::New(Thread::Current(), UserVisibleNameCString());
}

const char* AbstractType::UserVisibleNameCString() const {
  Thread* thread = Thread::Current();
  ZoneTextBuffer printer(thread->zone());
  PrintName(kUserVisibleName, &printer);
  return printer.buffer();
}

StringPtr AbstractType::ScrubbedName() const {
  return Symbols::New(Thread::Current(), ScrubbedNameCString());
}

const char* AbstractType::ScrubbedNameCString() const {
  Thread* thread = Thread::Current();
  ZoneTextBuffer printer(thread->zone());
  PrintName(kScrubbedName, &printer);
  return printer.buffer();
}

void AbstractType::PrintName(NameVisibility name_visibility,
                             BaseTextBuffer* printer) const {
  // All subclasses should implement this appropriately, so the only value that
  // should reach this implementation should be the null value.
  ASSERT(IsNull());
  // AbstractType is an abstract class.
  UNREACHABLE();
}

StringPtr AbstractType::ClassName() const {
  ASSERT(!IsFunctionType() && !IsRecordType());
  return Class::Handle(type_class()).Name();
}

bool AbstractType::IsNullType() const {
  return type_class_id() == kNullCid;
}

bool AbstractType::IsNeverType() const {
  return type_class_id() == kNeverCid;
}

bool AbstractType::IsSentinelType() const {
  return type_class_id() == kSentinelCid;
}

bool AbstractType::IsTopTypeForInstanceOf() const {
  const classid_t cid = type_class_id();
  if (cid == kDynamicCid || cid == kVoidCid) {
    return true;
  }
  if (cid == kInstanceCid) {  // Object type.
    return IsNullable();
  }
  if (cid == kFutureOrCid) {
    // FutureOr<T> where T is a top type behaves as a top type.
    return AbstractType::Handle(UnwrapFutureOr()).IsTopTypeForInstanceOf();
  }
  return false;
}

// Must be kept in sync with GenerateTypeIsTopTypeForSubtyping in
// stub_code_compiler.cc if any changes are made.
bool AbstractType::IsTopTypeForSubtyping() const {
  const classid_t cid = type_class_id();
  if (cid == kDynamicCid || cid == kVoidCid) {
    return true;
  }
  if (cid == kInstanceCid) {  // Object type.
    return !IsNonNullable();
  }
  if (cid == kFutureOrCid) {
    // FutureOr<T> where T is a top type behaves as a top type.
    return AbstractType::Handle(UnwrapFutureOr()).IsTopTypeForSubtyping();
  }
  return false;
}

bool AbstractType::IsIntType() const {
  return HasTypeClass() &&
         (type_class() == Type::Handle(Type::IntType()).type_class());
}

bool AbstractType::IsIntegerImplementationType() const {
  return HasTypeClass() &&
         (type_class() == IsolateGroup::Current()
                              ->object_store()
                              ->integer_implementation_class());
}

bool AbstractType::IsDoubleType() const {
  return HasTypeClass() &&
         (type_class() == Type::Handle(Type::Double()).type_class());
}

bool AbstractType::IsFloat32x4Type() const {
  // kFloat32x4Cid refers to the private class and cannot be used here.
  return HasTypeClass() &&
         (type_class() == Type::Handle(Type::Float32x4()).type_class());
}

bool AbstractType::IsFloat64x2Type() const {
  // kFloat64x2Cid refers to the private class and cannot be used here.
  return HasTypeClass() &&
         (type_class() == Type::Handle(Type::Float64x2()).type_class());
}

bool AbstractType::IsInt32x4Type() const {
  // kInt32x4Cid refers to the private class and cannot be used here.
  return HasTypeClass() &&
         (type_class() == Type::Handle(Type::Int32x4()).type_class());
}

bool AbstractType::IsStringType() const {
  return HasTypeClass() &&
         (type_class() == Type::Handle(Type::StringType()).type_class());
}

bool AbstractType::IsDartFunctionType() const {
  return HasTypeClass() &&
         (type_class() == Type::Handle(Type::DartFunctionType()).type_class());
}

bool AbstractType::IsDartClosureType() const {
  return (type_class_id() == kClosureCid);
}

bool AbstractType::IsDartRecordType() const {
  if (!HasTypeClass()) return false;
  const auto cid = type_class_id();
  return ((cid == kRecordCid) ||
          (cid == Class::Handle(
                      IsolateGroup::Current()->object_store()->record_class())
                      .id()));
}

bool AbstractType::IsFfiPointerType() const {
  return HasTypeClass() && type_class_id() == kPointerCid;
}

bool AbstractType::IsTypeClassAllowedBySpawnUri() const {
  if (!HasTypeClass()) return false;

  intptr_t cid = type_class_id();

  if (cid == kBoolCid) return true;
  if (cid == kDynamicCid) return true;
  if (cid == kInstanceCid) return true;  // Object.
  if (cid == kNeverCid) return true;
  if (cid == kNullCid) return true;
  if (cid == kVoidCid) return true;

  // These are not constant CID checks because kDoubleCid refers to _Double
  // not double, etc.
  ObjectStore* object_store = IsolateGroup::Current()->object_store();
  Type& candidate_type = Type::Handle();
  candidate_type = object_store->int_type();
  if (cid == candidate_type.type_class_id()) return true;
  candidate_type = object_store->double_type();
  if (cid == candidate_type.type_class_id()) return true;
  candidate_type = object_store->number_type();
  if (cid == candidate_type.type_class_id()) return true;
  candidate_type = object_store->string_type();
  if (cid == candidate_type.type_class_id()) return true;

  Class& candidate_cls = Class::Handle();
  candidate_cls = object_store->list_class();
  if (cid == candidate_cls.id()) return true;
  candidate_cls = object_store->map_class();
  if (cid == candidate_cls.id()) return true;
  candidate_cls = object_store->set_class();
  if (cid == candidate_cls.id()) return true;
  candidate_cls = object_store->capability_class();
  if (cid == candidate_cls.id()) return true;
  candidate_cls = object_store->send_port_class();
  if (cid == candidate_cls.id()) return true;
  candidate_cls = object_store->transferable_class();
  if (cid == candidate_cls.id()) return true;

  const auto& typed_data_lib =
      Library::Handle(object_store->typed_data_library());

#define IS_CHECK(name)                                                         \
  candidate_cls = typed_data_lib.LookupClass(Symbols::name##List());           \
  if (cid == candidate_cls.id()) {                                             \
    return true;                                                               \
  }
  DART_CLASS_LIST_TYPED_DATA(IS_CHECK)
#undef IS_CHECK

  return false;
}

AbstractTypePtr AbstractType::UnwrapFutureOr() const {
  if (!IsFutureOrType()) {
    return ptr();
  }
  if (arguments() == TypeArguments::null()) {
    return Type::dynamic_type().ptr();
  }
  Thread* thread = Thread::Current();
  REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread);
  TypeArguments& type_args = thread->TypeArgumentsHandle();
  type_args = arguments();
  REUSABLE_ABSTRACT_TYPE_HANDLESCOPE(thread);
  AbstractType& type_arg = thread->AbstractTypeHandle();
  type_arg = type_args.TypeAt(0);
  while (type_arg.IsFutureOrType()) {
    if (type_arg.arguments() == TypeArguments::null()) {
      return Type::dynamic_type().ptr();
    }
    type_args = type_arg.arguments();
    type_arg = type_args.TypeAt(0);
  }
  return type_arg.ptr();
}

bool AbstractType::IsSubtypeOf(
    const AbstractType& other,
    Heap::Space space,
    FunctionTypeMapping* function_type_equivalence) const {
  TRACE_TYPE_CHECKS_VERBOSE("  AbstractType::IsSubtypeOf(%s, %s)\n",
                            ToCString(), other.ToCString());
  ASSERT(IsFinalized());
  ASSERT(other.IsFinalized());
  // Reflexivity.
  if (ptr() == other.ptr()) {
    TRACE_TYPE_CHECKS_VERBOSE("   - result: true (same types)\n");
    return true;
  }
  // Right top type.
  if (other.IsTopTypeForSubtyping()) {
    TRACE_TYPE_CHECKS_VERBOSE("   - result: true (right is top)\n");
    return true;
  }
  // Left bottom type.
  // Any form of Never in weak mode maps to Null and Null is a bottom type in
  // weak mode. In strong mode, Never and Never* are bottom types. Therefore,
  // Never and Never* are bottom types regardless of weak/strong mode.
  // Note that we cannot encounter Never?, as it is normalized to Null.
  if (IsNeverType()) {
    ASSERT(!IsNullable());
    TRACE_TYPE_CHECKS_VERBOSE("   - result: true (left is Never)\n");
    return true;
  }
  // Left top type.
  if (IsDynamicType() || IsVoidType()) {
    TRACE_TYPE_CHECKS_VERBOSE("   - result: false (left is top)\n");
    return false;
  }
  // Left Null type.
  if (IsNullType()) {
    const bool result = Instance::NullIsAssignableTo(other);
    TRACE_TYPE_CHECKS_VERBOSE("   - result: %s (left is Null)\n",
                              (result ? "true" : "false"));
    return result;
  }
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  // Type parameters cannot be handled by Class::IsSubtypeOf().
  // When comparing two uninstantiated function types, one returning type
  // parameter K, the other returning type parameter V, we cannot assume that
  // K is a subtype of V, or vice versa. We only return true if K equals V, as
  // defined by TypeParameter::Equals.
  // The same rule applies when checking the upper bound of a still
  // uninstantiated type at compile time. Returning false will defer the test
  // to run time.
  // There are however some cases that can be decided at compile time.
  // For example, with class A<K, V extends K>, new A<T, T> called from within
  // a class B<T> will never require a run time bound check, even if T is
  // uninstantiated at compile time.
  if (IsTypeParameter()) {
    const TypeParameter& type_param = TypeParameter::Cast(*this);
    if (other.IsTypeParameter()) {
      const TypeParameter& other_type_param = TypeParameter::Cast(other);
      if (type_param.IsEquivalent(other_type_param,
                                  TypeEquality::kInSubtypeTest,
                                  function_type_equivalence)) {
        TRACE_TYPE_CHECKS_VERBOSE(
            "   - result: true (equivalent type parameters)\n");
        return true;
      }
    }
    const AbstractType& bound = AbstractType::Handle(zone, type_param.bound());
    ASSERT(bound.IsFinalized());
    if (bound.IsSubtypeOf(other, space, function_type_equivalence)) {
      TRACE_TYPE_CHECKS_VERBOSE("   - result: true (bound is a subtype)\n");
      return true;
    }
    // Apply additional subtyping rules if 'other' is 'FutureOr'.
    if (IsSubtypeOfFutureOr(zone, other, space, function_type_equivalence)) {
      TRACE_TYPE_CHECKS_VERBOSE(
          "   - result: true (type parameter is a subtype of FutureOr)\n");
      return true;
    }
    TRACE_TYPE_CHECKS_VERBOSE(
        "   - result: false (left is a type parameter)\n");
    return false;
  }
  if (other.IsTypeParameter()) {
    TRACE_TYPE_CHECKS_VERBOSE(
        "   - result: false (right is a type parameter)\n");
    return false;
  }
  // Function types cannot be handled by Class::IsSubtypeOf().
  if (IsFunctionType()) {
    // Any type that can be the type of a closure is a subtype of Function or
    // non-nullable Object.
    if (other.IsObjectType() || other.IsDartFunctionType()) {
      const bool result = !IsNullable() || !other.IsNonNullable();
      TRACE_TYPE_CHECKS_VERBOSE("   - result: %s (function vs non-function)\n",
                                (result ? "true" : "false"));
      return result;
    }
    if (other.IsFunctionType()) {
      // Check for two function types.
      if (IsNullable() && other.IsNonNullable()) {
        TRACE_TYPE_CHECKS_VERBOSE(
            "   - result: false (function nullability)\n");
        return false;
      }
      const bool result = FunctionType::Cast(*this).IsSubtypeOf(
          FunctionType::Cast(other), space, function_type_equivalence);
      TRACE_TYPE_CHECKS_VERBOSE("   - result: %s (function types)\n",
                                (result ? "true" : "false"));
      return result;
    }
    // Apply additional subtyping rules if 'other' is 'FutureOr'.
    if (IsSubtypeOfFutureOr(zone, other, space, function_type_equivalence)) {
      TRACE_TYPE_CHECKS_VERBOSE(
          "   - result: true (function type is a subtype of FutureOr)\n");
      return true;
    }
    // All possible supertypes for FunctionType have been checked.
    TRACE_TYPE_CHECKS_VERBOSE("   - result: false (function type)\n");
    return false;
  } else if (other.IsFunctionType()) {
    // FunctionTypes can only be subtyped by other FunctionTypes, so don't
    // fall through to class-based type tests.
    TRACE_TYPE_CHECKS_VERBOSE(
        "   - result: false (right is a function type)\n");
    return false;
  }
  // Record types cannot be handled by Class::IsSubtypeOf().
  if (IsRecordType()) {
    if (other.IsObjectType() || other.IsDartRecordType()) {
      const bool result = !IsNullable() || !other.IsNonNullable();
      TRACE_TYPE_CHECKS_VERBOSE("   - result: %s (record vs non-record)\n",
                                (result ? "true" : "false"));
      return result;
    }
    if (other.IsRecordType()) {
      // Check for two record types.
      if (IsNullable() && other.IsNonNullable()) {
        TRACE_TYPE_CHECKS_VERBOSE("   - result: false (record nullability)\n");
        return false;
      }
      const bool result = RecordType::Cast(*this).IsSubtypeOf(
          RecordType::Cast(other), space, function_type_equivalence);
      TRACE_TYPE_CHECKS_VERBOSE("   - result: %s (record types)\n",
                                (result ? "true" : "false"));
      return result;
    }
    // Apply additional subtyping rules if 'other' is 'FutureOr'.
    if (IsSubtypeOfFutureOr(zone, other, space, function_type_equivalence)) {
      TRACE_TYPE_CHECKS_VERBOSE(
          "   - result: true (record type is a subtype of FutureOr)\n");
      return true;
    }
    // All possible supertypes for record type have been checked.
    TRACE_TYPE_CHECKS_VERBOSE("   - result: false (record type)\n");
    return false;
  } else if (other.IsRecordType()) {
    // RecordTypes can only be subtyped by other RecordTypes, so don't
    // fall through to class-based type tests.
    TRACE_TYPE_CHECKS_VERBOSE("   - result: false (right is a record type)\n");
    return false;
  }
  ASSERT(IsType());
  const Class& type_cls = Class::Handle(zone, type_class());
  const bool result = Class::IsSubtypeOf(
      type_cls,
      TypeArguments::Handle(zone, Type::Cast(*this).GetInstanceTypeArguments(
                                      thread, /*canonicalize=*/false)),
      nullability(), other, space, function_type_equivalence);
  TRACE_TYPE_CHECKS_VERBOSE("   - result: %s (class type check)\n",
                            (result ? "true" : "false"));
  return result;
}

bool AbstractType::IsSubtypeOfFutureOr(
    Zone* zone,
    const AbstractType& other,
    Heap::Space space,
    FunctionTypeMapping* function_type_equivalence) const {
  if (other.IsFutureOrType()) {
    // This function is only called with a receiver that is either a function
    // type, record type, or an uninstantiated type parameter.
    // Therefore, it cannot be of class Future and we can spare the check.
    ASSERT(IsFunctionType() || IsRecordType() || IsTypeParameter());
    const TypeArguments& other_type_arguments =
        TypeArguments::Handle(zone, other.arguments());
    const AbstractType& other_type_arg =
        AbstractType::Handle(zone, other_type_arguments.TypeAtNullSafe(0));
    if (other_type_arg.IsTopTypeForSubtyping()) {
      return true;
    }
    // Retry the IsSubtypeOf check after unwrapping type arg of FutureOr.
    if (IsSubtypeOf(other_type_arg, space, function_type_equivalence)) {
      return true;
    }
  }
  return false;
}

uword AbstractType::ComputeHash() const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return 0;
}

const char* AbstractType::ToCString() const {
  // All subclasses should implement this appropriately, so the only value that
  // should reach this implementation should be the null value.
  ASSERT(IsNull());
  return "AbstractType: null";
}

void AbstractType::SetTypeTestingStub(const Code& stub) const {
  if (stub.IsNull()) {
    InitializeTypeTestingStubNonAtomic(stub);
    return;
  }

  auto& old = Code::Handle(Thread::Current()->zone());
  while (true) {
    // We load the old TTS and it's entrypoint.
    old = untag()->type_test_stub<std::memory_order_acquire>();
    uword old_entry_point = old.IsNull() ? 0 : old.EntryPoint();

    // If we can successfully update the entrypoint of the TTS, we will
    // unconditionally also set the [Code] of the TTS.
    //
    // Any competing writer would do the same, lose the compare-exchange, loop
    // around and continue loading the old [Code] TTS and continue to lose the
    // race until we have finally also updated the [Code] TTS.
    if (untag()->type_test_stub_entry_point_.compare_exchange_strong(
            old_entry_point, stub.EntryPoint())) {
      untag()->set_type_test_stub<std::memory_order_release>(stub.ptr());
      return;
    }
  }
}

void AbstractType::InitializeTypeTestingStubNonAtomic(const Code& stub) const {
  if (stub.IsNull()) {
    // This only happens during bootstrapping when creating Type objects before
    // we have the instructions.
    ASSERT(type_class_id() == kDynamicCid || type_class_id() == kVoidCid);
    StoreNonPointer(&untag()->type_test_stub_entry_point_, 0);
    untag()->set_type_test_stub(stub.ptr());
    return;
  }

  StoreNonPointer(&untag()->type_test_stub_entry_point_, stub.EntryPoint());
  untag()->set_type_test_stub(stub.ptr());
}

TypePtr Type::NullType() {
  return IsolateGroup::Current()->object_store()->null_type();
}

TypePtr Type::DynamicType() {
  return Object::dynamic_type().ptr();
}

TypePtr Type::VoidType() {
  return Object::void_type().ptr();
}

TypePtr Type::NeverType() {
  return IsolateGroup::Current()->object_store()->never_type();
}

TypePtr Type::ObjectType() {
  return IsolateGroup::Current()->object_store()->object_type();
}

TypePtr Type::BoolType() {
  return IsolateGroup::Current()->object_store()->bool_type();
}

TypePtr Type::IntType() {
  return IsolateGroup::Current()->object_store()->int_type();
}

TypePtr Type::NullableIntType() {
  return IsolateGroup::Current()->object_store()->nullable_int_type();
}

TypePtr Type::SmiType() {
  return IsolateGroup::Current()->object_store()->smi_type();
}

TypePtr Type::MintType() {
  return IsolateGroup::Current()->object_store()->mint_type();
}

TypePtr Type::Double() {
  return IsolateGroup::Current()->object_store()->double_type();
}

TypePtr Type::NullableDouble() {
  return IsolateGroup::Current()->object_store()->nullable_double_type();
}

TypePtr Type::Float32x4() {
  return IsolateGroup::Current()->object_store()->float32x4_type();
}

TypePtr Type::Float64x2() {
  return IsolateGroup::Current()->object_store()->float64x2_type();
}

TypePtr Type::Int32x4() {
  return IsolateGroup::Current()->object_store()->int32x4_type();
}

TypePtr Type::Number() {
  return IsolateGroup::Current()->object_store()->number_type();
}

TypePtr Type::NullableNumber() {
  return IsolateGroup::Current()->object_store()->nullable_number_type();
}

TypePtr Type::StringType() {
  return IsolateGroup::Current()->object_store()->string_type();
}

TypePtr Type::ArrayType() {
  return IsolateGroup::Current()->object_store()->array_type();
}

TypePtr Type::DartFunctionType() {
  return IsolateGroup::Current()->object_store()->function_type();
}

TypePtr Type::DartTypeType() {
  return IsolateGroup::Current()->object_store()->type_type();
}

TypePtr Type::NewNonParameterizedType(const Class& type_class) {
  ASSERT(type_class.NumTypeArguments() == 0);
  if (type_class.IsNullClass()) {
    return Type::NullType();
  }
  if (type_class.IsDynamicClass()) {
    return Type::DynamicType();
  }
  if (type_class.IsVoidClass()) {
    return Type::VoidType();
  }
  // It is too early to use the class finalizer, as type_class may not be named
  // yet, so do not call DeclarationType().
  Type& type = Type::Handle(type_class.declaration_type());
  if (type.IsNull()) {
    type = Type::New(Class::Handle(type_class.ptr()),
                     Object::null_type_arguments(), Nullability::kNonNullable);
    type.SetIsFinalized();
    type ^= type.Canonicalize(Thread::Current());
    type_class.set_declaration_type(type);
  }
  ASSERT(type.IsFinalized());
  return type.ptr();
}

TypePtr Type::ToNullability(Nullability value, Heap::Space space) const {
  if (nullability() == value) {
    return ptr();
  }
  // Type parameter instantiation may request a nullability change, which should
  // be ignored for types dynamic and void. Type Null cannot be the result of
  // instantiating a non-nullable type parameter (TypeError thrown).
  const classid_t cid = type_class_id();
  if (cid == kDynamicCid || cid == kVoidCid || cid == kNullCid) {
    return ptr();
  }
  if (cid == kNeverCid && value == Nullability::kNullable) {
    // Normalize Never? to Null.
    return Type::NullType();
  }
  // Clone type and set new nullability.
  Type& type = Type::Handle();
  // Always cloning in old space and removing space parameter would not satisfy
  // currently existing requests for type instantiation in new space.
  // Load with relaxed atomics to prevent data race with updating type
  // testing stub.
  type ^= Object::Clone(*this, space, /*load_with_relaxed_atomics=*/true);
  type.set_nullability(value);
  type.SetHash(0);
  type.InitializeTypeTestingStubNonAtomic(
      Code::Handle(TypeTestingStubGenerator::DefaultCodeForType(type)));
  if (IsCanonical()) {
    // Object::Clone does not clone canonical bit.
    ASSERT(!type.IsCanonical());
    type ^= type.Canonicalize(Thread::Current());
  }
  return type.ptr();
}

FunctionTypePtr FunctionType::ToNullability(Nullability value,
                                            Heap::Space space) const {
  if (nullability() == value) {
    return ptr();
  }
  // Clone function type and set new nullability.
  FunctionType& type = FunctionType::Handle(FunctionType::Clone(*this, space));
  type.set_nullability(value);
  type.SetHash(0);
  type.InitializeTypeTestingStubNonAtomic(
      Code::Handle(TypeTestingStubGenerator::DefaultCodeForType(type)));
  if (IsCanonical()) {
    // Object::Clone does not clone canonical bit.
    ASSERT(!type.IsCanonical());
    type ^= type.Canonicalize(Thread::Current());
  }
  return type.ptr();
}

classid_t Type::type_class_id() const {
  return untag()->type_class_id();
}

ClassPtr Type::type_class() const {
  return IsolateGroup::Current()->class_table()->At(type_class_id());
}

bool Type::IsInstantiated(Genericity genericity,
                          intptr_t num_free_fun_type_params) const {
  if (type_state() == UntaggedType::kFinalizedInstantiated) {
    return true;
  }
  if ((genericity == kAny) && (num_free_fun_type_params == kAllFree) &&
      (type_state() == UntaggedType::kFinalizedUninstantiated)) {
    return false;
  }
  if (arguments() == TypeArguments::null()) {
    return true;
  }
  const TypeArguments& args = TypeArguments::Handle(arguments());
  return args.IsSubvectorInstantiated(0, args.Length(), genericity,
                                      num_free_fun_type_params);
}

AbstractTypePtr Type::InstantiateFrom(
    const TypeArguments& instantiator_type_arguments,
    const TypeArguments& function_type_arguments,
    intptr_t num_free_fun_type_params,
    Heap::Space space,
    FunctionTypeMapping* function_type_mapping,
    intptr_t num_parent_type_args_adjustment) const {
  Zone* zone = Thread::Current()->zone();
  ASSERT(IsFinalized());
  ASSERT(!IsInstantiated());
  // Note that the type class has to be resolved at this time, but not
  // necessarily finalized yet. We may be checking bounds at compile time or
  // finalizing the type argument vector of a recursive type.
  const Class& cls = Class::Handle(zone, type_class());
  TypeArguments& type_arguments = TypeArguments::Handle(zone, arguments());
  ASSERT(type_arguments.Length() == cls.NumTypeParameters());
  type_arguments = type_arguments.InstantiateFrom(
      instantiator_type_arguments, function_type_arguments,
      num_free_fun_type_params, space, function_type_mapping,
      num_parent_type_args_adjustment);
  // A returned empty_type_arguments indicates a failed instantiation in dead
  // code that must be propagated up to the caller, the optimizing compiler.
  if (type_arguments.ptr() == Object::empty_type_arguments().ptr()) {
    return Type::null();
  }
  // This uninstantiated type is not modified, as it can be instantiated
  // with different instantiators. Allocate a new instantiated version of it.
  const Type& instantiated_type =
      Type::Handle(zone, Type::New(cls, type_arguments, nullability(), space));
  instantiated_type.SetIsFinalized();
  // Canonicalization is not part of instantiation.
  return instantiated_type.NormalizeFutureOrType(space);
}

AbstractTypePtr Type::UpdateFunctionTypes(
    intptr_t num_parent_type_args_adjustment,
    intptr_t num_free_fun_type_params,
    Heap::Space space,
    FunctionTypeMapping* function_type_mapping) const {
  ASSERT(IsFinalized());
  ASSERT(num_parent_type_args_adjustment >= 0);
  if (arguments() == Object::null()) {
    return ptr();
  }
  Zone* zone = Thread::Current()->zone();
  const auto& type_args = TypeArguments::Handle(zone, arguments());
  const auto& updated_type_args = TypeArguments::Handle(
      zone, type_args.UpdateFunctionTypes(num_parent_type_args_adjustment,
                                          num_free_fun_type_params, space,
                                          function_type_mapping));
  if (type_args.ptr() == updated_type_args.ptr()) {
    return ptr();
  }
  const Class& cls = Class::Handle(zone, type_class());
  const Type& new_type = Type::Handle(
      zone, Type::New(cls, updated_type_args, nullability(), space));
  new_type.SetIsFinalized();
  return new_type.ptr();
}

// Certain built-in classes are treated as syntactically equivalent.
static classid_t NormalizeClassIdForSyntacticalTypeEquality(classid_t cid) {
  if (IsIntegerClassId(cid)) {
    return Type::Handle(Type::IntType()).type_class_id();
  } else if (IsStringClassId(cid)) {
    return Type::Handle(Type::StringType()).type_class_id();
  } else if (cid == kDoubleCid) {
    return Type::Handle(Type::Double()).type_class_id();
  } else if (IsTypeClassId(cid)) {
    return Type::Handle(Type::DartTypeType()).type_class_id();
  } else if (IsArrayClassId(cid)) {
    return Class::Handle(IsolateGroup::Current()->object_store()->list_class())
        .id();
  }
  return cid;
}

bool Type::IsEquivalent(const Instance& other,
                        TypeEquality kind,
                        FunctionTypeMapping* function_type_equivalence) const {
  ASSERT(!IsNull());
  if (ptr() == other.ptr()) {
    return true;
  }
  if (!other.IsType()) {
    return false;
  }
  const Type& other_type = Type::Cast(other);
  const classid_t type_cid = type_class_id();
  const classid_t other_type_cid = other_type.type_class_id();
  if (type_cid != other_type_cid) {
    if ((kind != TypeEquality::kSyntactical) ||
        (NormalizeClassIdForSyntacticalTypeEquality(type_cid) !=
         NormalizeClassIdForSyntacticalTypeEquality(other_type_cid))) {
      return false;
    }
  }
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  ASSERT(
      Class::Handle(zone, type_class()).NumTypeParameters(thread) ==
      Class::Handle(zone, other_type.type_class()).NumTypeParameters(thread));

  if (!IsNullabilityEquivalent(thread, other_type, kind)) {
    return false;
  }
  if (!IsFinalized() || !other_type.IsFinalized()) {
    ASSERT(kind != TypeEquality::kCanonical);
    return false;  // Too early to decide if equal.
  }
  if (arguments() == other_type.arguments()) {
    return true;
  }
  const TypeArguments& type_args =
      TypeArguments::Handle(zone, this->arguments());
  const TypeArguments& other_type_args =
      TypeArguments::Handle(zone, other_type.arguments());
  return type_args.IsEquivalent(other_type_args, kind,
                                function_type_equivalence);
}

bool FunctionType::IsEquivalent(
    const Instance& other,
    TypeEquality kind,
    FunctionTypeMapping* function_type_equivalence) const {
  ASSERT(!IsNull());
  if (ptr() == other.ptr()) {
    return true;
  }
  if (!other.IsFunctionType()) {
    return false;
  }
  const FunctionType& other_type = FunctionType::Cast(other);
  if ((packed_parameter_counts() != other_type.packed_parameter_counts()) ||
      (packed_type_parameter_counts() !=
       other_type.packed_type_parameter_counts())) {
    // Different number of type parameters or parameters.
    return false;
  }
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  if (!IsNullabilityEquivalent(thread, other_type, kind)) {
    return false;
  }
  if (!IsFinalized() || !other_type.IsFinalized()) {
    ASSERT(kind != TypeEquality::kCanonical);
    return false;  // Too early to decide if equal.
  }
  FunctionTypeMapping scope(zone, &function_type_equivalence, *this,
                            other_type);

  // Equal function types must have equal signature types and equal optional
  // named arguments.
  // Compare function type parameters and their bounds.
  // Check the type parameters and bounds of generic functions.
  if (!HasSameTypeParametersAndBounds(other_type, kind,
                                      function_type_equivalence)) {
    return false;
  }
  AbstractType& param_type = Type::Handle(zone);
  AbstractType& other_param_type = Type::Handle(zone);
  // Check the result type.
  param_type = result_type();
  other_param_type = other_type.result_type();
  if (!param_type.IsEquivalent(other_param_type, kind,
                               function_type_equivalence)) {
    return false;
  }
  // Check the types of all parameters.
  const intptr_t num_params = NumParameters();
  ASSERT(other_type.NumParameters() == num_params);
  for (intptr_t i = 0; i < num_params; i++) {
    param_type = ParameterTypeAt(i);
    other_param_type = other_type.ParameterTypeAt(i);
    // Use contravariant order in case we test for subtyping.
    if (!other_param_type.IsEquivalent(param_type, kind,
                                       function_type_equivalence)) {
      return false;
    }
  }
  if (HasOptionalNamedParameters()) {
    ASSERT(other_type.HasOptionalNamedParameters());  // Same packed counts.
    for (intptr_t i = num_fixed_parameters(); i < num_params; i++) {
      if (ParameterNameAt(i) != other_type.ParameterNameAt(i)) {
        return false;
      }
      if (IsRequiredAt(i) != other_type.IsRequiredAt(i)) {
        return false;
      }
    }
  }
  return true;
}

bool Type::IsDeclarationTypeOf(const Class& cls) const {
  ASSERT(type_class() == cls.ptr());
  if (cls.IsNullClass()) {
    return true;
  }
  if (cls.IsGeneric() || cls.IsClosureClass()) {
    return false;
  }
  return nullability() == Nullability::kNonNullable;
}

// Keep in sync with TypeSerializationCluster::IsInCanonicalSet.
AbstractTypePtr Type::Canonicalize(Thread* thread) const {
  Zone* zone = thread->zone();
  ASSERT(IsFinalized());
  if (IsCanonical()) {
#ifdef DEBUG
    TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
    ASSERT(type_args.IsCanonical());
    ASSERT(type_args.IsOld());
#endif
    return this->ptr();
  }
  auto isolate_group = thread->isolate_group();
  const classid_t cid = type_class_id();
  if (cid == kDynamicCid) {
    ASSERT(Object::dynamic_type().IsCanonical());
    return Object::dynamic_type().ptr();
  }

  if (cid == kVoidCid) {
    ASSERT(Object::void_type().IsCanonical());
    return Object::void_type().ptr();
  }

  const Class& cls = Class::Handle(zone, type_class());

  // Fast canonical lookup/registry for simple types.
  if (IsDeclarationTypeOf(cls)) {
    ASSERT(!cls.IsNullClass() || IsNullable());
    Type& type = Type::Handle(zone, cls.declaration_type());
    if (type.IsNull()) {
      ASSERT(!cls.ptr()->untag()->InVMIsolateHeap() ||
             (isolate_group == Dart::vm_isolate_group()));
      // Canonicalize the type arguments of the supertype, if any.
      TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
      type_args = type_args.Canonicalize(thread);
      set_arguments(type_args);
      type = cls.declaration_type();
      // May be set while canonicalizing type args.
      if (type.IsNull()) {
        SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
        // Recheck if type exists.
        type = cls.declaration_type();
        if (type.IsNull()) {
          if (this->IsNew()) {
            type ^= Object::Clone(*this, Heap::kOld);
          } else {
            type = this->ptr();
          }
          ASSERT(type.IsOld());
          type.ComputeHash();
          type.SetCanonical();
          cls.set_declaration_type(type);
          return type.ptr();
        }
      }
    }
    ASSERT(this->Equals(type));
    ASSERT(type.IsOld());
    if (type.IsCanonical()) {
      return type.ptr();
    }
  }

  Type& type = Type::Handle(zone);
  ObjectStore* object_store = isolate_group->object_store();
  {
    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
    CanonicalTypeSet table(zone, object_store->canonical_types());
    type ^= table.GetOrNull(CanonicalTypeKey(*this));
    ASSERT(object_store->canonical_types() == table.Release().ptr());
  }
  if (type.IsNull()) {
    // The type was not found in the table. It is not canonical yet.

    // Canonicalize the type arguments.
    TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
    ASSERT(type_args.IsNull() ||
           (type_args.Length() == cls.NumTypeParameters()));
    type_args = type_args.Canonicalize(thread);
    set_arguments(type_args);
    ASSERT(type_args.IsNull() || type_args.IsOld());

    // Check to see if the type got added to canonical table as part of the
    // type arguments canonicalization.
    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
    CanonicalTypeSet table(zone, object_store->canonical_types());
    type ^= table.GetOrNull(CanonicalTypeKey(*this));
    if (type.IsNull()) {
      // Add this type into the canonical table of types.
      if (this->IsNew()) {
        type ^= Object::Clone(*this, Heap::kOld);
      } else {
        type = this->ptr();
      }
      ASSERT(type.IsOld());
      type.SetCanonical();  // Mark object as being canonical.
      bool present = table.Insert(type);
      ASSERT(!present);
    }
    object_store->set_canonical_types(table.Release());
  }
  return type.ptr();
}

void Type::EnumerateURIs(URIs* uris) const {
  if (IsDynamicType() || IsVoidType() || IsNeverType()) {
    return;
  }
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const Class& cls = Class::Handle(zone, type_class());
  const String& name = String::Handle(zone, cls.UserVisibleName());
  const Library& library = Library::Handle(zone, cls.library());
  const String& uri = String::Handle(zone, library.url());
  AddURI(uris, name, uri);
  const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
  type_args.EnumerateURIs(uris);
}

void Type::PrintName(NameVisibility name_visibility,
                     BaseTextBuffer* printer) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const Class& cls = Class::Handle(zone, type_class());
  const TypeParameters& params =
      TypeParameters::Handle(zone, cls.type_parameters());
  printer->AddString(cls.NameCString(name_visibility));
  const TypeArguments& args = TypeArguments::Handle(zone, arguments());
  intptr_t num_type_params = 0;
  if (cls.is_declaration_loaded()) {
    num_type_params = cls.NumTypeParameters(thread);
  } else if (!args.IsNull() || args.ptr() != params.defaults()) {
    num_type_params = args.Length();
  }
  if (num_type_params == 0) {
    // Do nothing.
  } else {
    args.PrintSubvectorName(0, num_type_params, name_visibility, printer);
  }
  printer->AddString(NullabilitySuffix(name_visibility));
  // The name is only used for type checking and debugging purposes.
  // Unless profiling data shows otherwise, it is not worth caching the name in
  // the type.
}

uword Type::ComputeHash() const {
  ASSERT(IsFinalized());
  uint32_t result = type_class_id();
  result = CombineHashes(result, static_cast<uint32_t>(nullability()));
  uint32_t type_args_hash = TypeArguments::kAllDynamicHash;
  if (arguments() != TypeArguments::null()) {
    const TypeArguments& args = TypeArguments::Handle(arguments());
    type_args_hash = args.Hash();
  }
  result = CombineHashes(result, type_args_hash);
  result = FinalizeHash(result, kHashBits);
  SetHash(result);
  return result;
}

uword FunctionType::ComputeHash() const {
  ASSERT(IsFinalized());
  uint32_t result =
      CombineHashes(packed_parameter_counts(), packed_type_parameter_counts());
  result = CombineHashes(result, static_cast<uint32_t>(nullability()));
  AbstractType& type = AbstractType::Handle();
  const intptr_t num_type_params = NumTypeParameters();
  if (num_type_params > 0) {
    const TypeParameters& type_params =
        TypeParameters::Handle(type_parameters());
    const TypeArguments& bounds = TypeArguments::Handle(type_params.bounds());
    result = CombineHashes(result, bounds.Hash());
    // Since the default arguments are ignored when comparing two generic
    // function types for type equality, the hash does not depend on them.
  }
  type = result_type();
  result = CombineHashes(result, type.Hash());
  const intptr_t num_params = NumParameters();
  for (intptr_t i = 0; i < num_params; i++) {
    type = ParameterTypeAt(i);
    result = CombineHashes(result, type.Hash());
  }
  if (HasOptionalNamedParameters()) {
    String& param_name = String::Handle();
    for (intptr_t i = num_fixed_parameters(); i < num_params; i++) {
      param_name = ParameterNameAt(i);
      result = CombineHashes(result, param_name.Hash());
    }
    // Required flag is not hashed, see comment above about legacy type.
  }
  result = FinalizeHash(result, kHashBits);
  SetHash(result);
  return result;
}

void Type::set_type_class(const Class& value) const {
  ASSERT(!value.IsNull());
  set_type_class_id(value.id());
}

void Type::set_arguments(const TypeArguments& value) const {
  ASSERT(!IsCanonical());
  ASSERT(value.IsNull() ||
         // Do not attempt to query number of type parameters
         // before class declaration is fully loaded.
         !Class::Handle(type_class()).is_declaration_loaded() ||
         // Relax assertion in order to support invalid generic types
         // created in ClosureMirror_function.
         (type_class_id() == kInstanceCid) ||
         value.Length() == Class::Handle(type_class()).NumTypeParameters());
  untag()->set_arguments(value.ptr());
}

TypeArgumentsPtr Type::GetInstanceTypeArguments(Thread* thread,
                                                bool canonicalize) const {
  Zone* zone = thread->zone();
  const auto& cls = Class::Handle(zone, type_class());
  const auto& args = TypeArguments::Handle(zone, arguments());
  return cls.GetInstanceTypeArguments(thread, args, canonicalize);
}

TypePtr Type::New(Heap::Space space) {
  return Object::Allocate<Type>(space);
}

TypePtr Type::New(const Class& clazz,
                  const TypeArguments& arguments,
                  Nullability nullability,
                  Heap::Space space) {
  Zone* Z = Thread::Current()->zone();
  const Type& result = Type::Handle(Z, Type::New(space));
  result.SetHash(0);
  result.set_flags(0);
  result.set_nullability(nullability);
  result.set_type_state(UntaggedAbstractType::kAllocated);
  result.set_type_class(clazz);
  result.set_arguments(arguments);

  result.InitializeTypeTestingStubNonAtomic(
      Code::Handle(Z, TypeTestingStubGenerator::DefaultCodeForType(result)));
  return result.ptr();
}

void Type::set_type_class_id(intptr_t id) const {
  ASSERT(Utils::IsUint(UntaggedObject::kClassIdTagSize, id));
  // We should never need a Type object for a top-level class.
  ASSERT(!ClassTable::IsTopLevelCid(id));
  ASSERT(id != kIllegalCid);
  ASSERT(!IsInternalOnlyClassId(id));
  untag()->set_type_class_id(id);
}

const char* Type::ToCString() const {
  if (IsNull()) {
    return "Type: null";
  }
  Zone* zone = Thread::Current()->zone();
  ZoneTextBuffer args(zone);
  const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
  const char* args_cstr = "";
  if (!type_args.IsNull()) {
    type_args.PrintSubvectorName(0, type_args.Length(), kInternalName, &args);
    args_cstr = args.buffer();
  }
  const Class& cls = Class::Handle(zone, type_class());
  const char* class_name;
  const String& name = String::Handle(zone, cls.Name());
  class_name = name.IsNull() ? "<null>" : name.ToCString();
  const char* suffix = NullabilitySuffix(kInternalName);
  return OS::SCreate(zone, "Type: %s%s%s", class_name, args_cstr, suffix);
}

AbstractTypePtr FunctionType::Canonicalize(Thread* thread) const {
  ASSERT(IsFinalized());
  Zone* zone = thread->zone();
  if (IsCanonical()) {
#ifdef DEBUG
    // Verify that all fields are allocated in old space and are canonical.
    if (IsGeneric()) {
      const TypeParameters& type_params =
          TypeParameters::Handle(zone, type_parameters());
      ASSERT(type_params.IsOld());
      TypeArguments& type_args = TypeArguments::Handle(zone);
      type_args = type_params.bounds();
      ASSERT(type_args.IsOld());
      ASSERT(type_args.IsCanonical());
      type_args = type_params.defaults();
      ASSERT(type_args.IsOld());
      ASSERT(type_args.IsCanonical());
    }
    AbstractType& type = AbstractType::Handle(zone);
    type = result_type();
    ASSERT(type.IsOld());
    ASSERT(type.IsCanonical());
    ASSERT(Array::Handle(zone, parameter_types()).IsOld());
    ASSERT(Array::Handle(zone, named_parameter_names()).IsOld());
    const intptr_t num_params = NumParameters();
    for (intptr_t i = 0; i < num_params; i++) {
      type = ParameterTypeAt(i);
      ASSERT(type.IsOld());
      ASSERT(type.IsCanonical());
    }
#endif
    return ptr();
  }
  auto isolate_group = thread->isolate_group();
  ObjectStore* object_store = isolate_group->object_store();
  FunctionType& sig = FunctionType::Handle(zone);
  {
    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
    CanonicalFunctionTypeSet table(zone,
                                   object_store->canonical_function_types());
    sig ^= table.GetOrNull(CanonicalFunctionTypeKey(*this));
    ASSERT(object_store->canonical_function_types() == table.Release().ptr());
  }
  if (sig.IsNull()) {
    // The function type was not found in the table. It is not canonical yet.
    // Canonicalize its type parameters and types.

    // Clone this function type to the old heap and update
    // owners of type parameters.
    FunctionType& new_sig = FunctionType::Handle(zone);
    if (this->IsNew()) {
      new_sig ^= FunctionType::Clone(*this, Heap::kOld);
    } else {
      new_sig ^= this->ptr();
    }
    ASSERT(new_sig.IsOld());

    if (new_sig.IsGeneric()) {
      const TypeParameters& type_params =
          TypeParameters::Handle(zone, new_sig.type_parameters());
      ASSERT(type_params.IsOld());
      TypeArguments& type_args = TypeArguments::Handle(zone);
      type_args = type_params.bounds();
      if (!type_args.IsCanonical()) {
        type_args = type_args.Canonicalize(thread);
        type_params.set_bounds(type_args);
      }
      type_args = type_params.defaults();
      if (!type_args.IsCanonical()) {
        type_args = type_args.Canonicalize(thread);
        type_params.set_defaults(type_args);
      }
    }
    AbstractType& type = AbstractType::Handle(zone);
    type = new_sig.result_type();
    if (!type.IsCanonical()) {
      type = type.Canonicalize(thread);
      new_sig.set_result_type(type);
    }
    ASSERT(Array::Handle(zone, new_sig.parameter_types()).IsOld());
    ASSERT(Array::Handle(zone, new_sig.named_parameter_names()).IsOld());
    const intptr_t num_params = new_sig.NumParameters();
    for (intptr_t i = 0; i < num_params; i++) {
      type = new_sig.ParameterTypeAt(i);
      if (!type.IsCanonical()) {
        type = type.Canonicalize(thread);
        new_sig.SetParameterTypeAt(i, type);
      }
    }
    // Check to see if the function type got added to canonical table
    // during canonicalization of its signature types.
    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
    CanonicalFunctionTypeSet table(zone,
                                   object_store->canonical_function_types());
    sig ^= table.GetOrNull(CanonicalFunctionTypeKey(new_sig));
    if (sig.IsNull()) {
      // Add this function type into the canonical table of function types.
      sig = new_sig.ptr();
      ASSERT(sig.IsOld());
      sig.SetCanonical();  // Mark object as being canonical.
      bool present = table.Insert(sig);
      ASSERT(!present);
    }
    object_store->set_canonical_function_types(table.Release());
  }
  return sig.ptr();
}

void FunctionType::EnumerateURIs(URIs* uris) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  AbstractType& type = AbstractType::Handle(zone);
  const intptr_t num_params = NumParameters();
  for (intptr_t i = 0; i < num_params; i++) {
    type = ParameterTypeAt(i);
    type.EnumerateURIs(uris);
  }
  // Handle result type last, since it appears last in the user visible name.
  type = result_type();
  type.EnumerateURIs(uris);
}

void FunctionType::PrintName(NameVisibility name_visibility,
                             BaseTextBuffer* printer) const {
  const char* suffix = NullabilitySuffix(name_visibility);
  if (suffix[0] != '\0') {
    printer->AddString("(");
  }
  FunctionType::Cast(*this).Print(name_visibility, printer);
  if (suffix[0] != '\0') {
    printer->AddString(")");
    printer->AddString(suffix);
  }
}

TypeParameterPtr TypeParameter::ToNullability(Nullability value,
                                              Heap::Space space) const {
  if (nullability() == value) {
    return ptr();
  }
  // Clone type parameter and set new nullability.
  TypeParameter& type_parameter = TypeParameter::Handle();
  type_parameter ^= Object::Clone(*this, space);
  type_parameter.set_nullability(value);
  type_parameter.SetHash(0);
  type_parameter.InitializeTypeTestingStubNonAtomic(Code::Handle(
      TypeTestingStubGenerator::DefaultCodeForType(type_parameter)));
  if (IsCanonical()) {
    // Object::Clone does not clone canonical bit.
    ASSERT(!type_parameter.IsCanonical());
    ASSERT(IsFinalized());
    ASSERT(type_parameter.IsFinalized());
    type_parameter ^= type_parameter.Canonicalize(Thread::Current());
  }
  return type_parameter.ptr();
}

bool TypeParameter::IsInstantiated(Genericity genericity,
                                   intptr_t num_free_fun_type_params) const {
  // Bounds of class type parameters are ignored in the VM.
  if (IsClassTypeParameter()) {
    return genericity == kFunctions;
  }
  ASSERT(IsFunctionTypeParameter());
  return (genericity == kCurrentClass) || (index() >= num_free_fun_type_params);
}

bool TypeParameter::IsEquivalent(
    const Instance& other,
    TypeEquality kind,
    FunctionTypeMapping* function_type_equivalence) const {
  TRACE_TYPE_CHECKS_VERBOSE("  TypeParameter::IsEquivalent(%s, %s, kind %d)\n",
                            ToCString(), other.ToCString(),
                            static_cast<int>(kind));
  if (ptr() == other.ptr()) {
    TRACE_TYPE_CHECKS_VERBOSE("   - result: true (same types)\n");
    return true;
  }
  if (!other.IsTypeParameter()) {
    TRACE_TYPE_CHECKS_VERBOSE(
        "   - result: false (other is not a type parameter)\n");
    return false;
  }
  const TypeParameter& other_type_param = TypeParameter::Cast(other);
  ASSERT(IsFinalized() && other_type_param.IsFinalized());
  // Compare index, base and owner.
  if (IsFunctionTypeParameter()) {
    if (!other_type_param.IsFunctionTypeParameter()) {
      TRACE_TYPE_CHECKS_VERBOSE(
          "   - result: false (other is not a function type parameter)\n");
      return false;
    }
    if ((parameterized_function_type() !=
         other_type_param.parameterized_function_type()) &&
        ((function_type_equivalence == nullptr) ||
         !function_type_equivalence->ContainsOwnersOfTypeParameters(
             *this, other_type_param))) {
      TRACE_TYPE_CHECKS_VERBOSE(
          "   - result: false (owners are not equivalent)\n");
      return false;
    }
  } else {
    if (!other_type_param.IsClassTypeParameter()) {
      TRACE_TYPE_CHECKS_VERBOSE(
          "   - result: false (other is not a class type parameter)\n");
      return false;
    }
    if (parameterized_class_id() != other_type_param.parameterized_class_id()) {
      TRACE_TYPE_CHECKS_VERBOSE(
          "   - result: false (parameterized class id)\n");
      return false;
    }
  }
  if (base() != other_type_param.base() ||
      index() != other_type_param.index()) {
    TRACE_TYPE_CHECKS_VERBOSE("   - result: false (mismatch base/index)\n");
    return false;
  }
  if (!IsNullabilityEquivalent(Thread::Current(), other_type_param, kind)) {
    TRACE_TYPE_CHECKS_VERBOSE("   - result: false (mismatch nullability)\n");
    return false;
  }
  TRACE_TYPE_CHECKS_VERBOSE("   - result: true\n");
  return true;
}

void TypeParameter::set_owner(const Object& value) const {
  ASSERT((IsFunctionTypeParameter() && value.IsFunctionType()) ||
         (IsClassTypeParameter() && value.IsSmi()));
  untag()->set_owner(value.ptr());
}

classid_t TypeParameter::parameterized_class_id() const {
  if (IsClassTypeParameter()) {
    return Smi::Value(Smi::RawCast(untag()->owner()));
  } else {
    return kFunctionCid;
  }
}
void TypeParameter::set_parameterized_class_id(classid_t value) const {
  ASSERT(IsClassTypeParameter());
  untag()->set_owner(Smi::New(value));
}

ClassPtr TypeParameter::parameterized_class() const {
  if (IsClassTypeParameter()) {
    const classid_t cid = parameterized_class_id();
    if (cid != kIllegalCid) {
      return IsolateGroup::Current()->class_table()->At(cid);
    }
  }
  return Class::null();
}

FunctionTypePtr TypeParameter::parameterized_function_type() const {
  ASSERT(IsFunctionTypeParameter());
  return FunctionType::RawCast(untag()->owner());
}

void TypeParameter::set_base(intptr_t value) const {
  ASSERT(value >= 0);
  ASSERT(Utils::IsUint(16, value));
  StoreNonPointer(&untag()->base_, value);
}

void TypeParameter::set_index(intptr_t value) const {
  ASSERT(value >= 0);
  ASSERT(Utils::IsUint(16, value));
  StoreNonPointer(&untag()->index_, value);
}

AbstractTypePtr TypeParameter::bound() const {
  if (IsFunctionTypeParameter()) {
    const auto& owner = FunctionType::Handle(parameterized_function_type());
    const auto& type_parameters =
        TypeParameters::Handle(owner.type_parameters());
    return type_parameters.BoundAt(index() - base());
  } else {
    const auto& owner = Class::Handle(parameterized_class());
    if (owner.IsNull()) {
      return IsolateGroup::Current()->object_store()->nullable_object_type();
    }
    const auto& type_parameters =
        TypeParameters::Handle(owner.type_parameters());
    return type_parameters.BoundAt(index() - base());
  }
}

AbstractTypePtr TypeParameter::GetFromTypeArguments(
    const TypeArguments& instantiator_type_arguments,
    const TypeArguments& function_type_arguments) const {
  ASSERT(IsFinalized());
  const TypeArguments& type_args = IsFunctionTypeParameter()
                                       ? function_type_arguments
                                       : instantiator_type_arguments;
  return type_args.TypeAtNullSafe(index());
}

AbstractTypePtr TypeParameter::InstantiateFrom(
    const TypeArguments& instantiator_type_arguments,
    const TypeArguments& function_type_arguments,
    intptr_t num_free_fun_type_params,
    Heap::Space space,
    FunctionTypeMapping* function_type_mapping,
    intptr_t num_parent_type_args_adjustment) const {
  Zone* zone = Thread::Current()->zone();
  AbstractType& result = AbstractType::Handle(zone);
  bool substituted = false;
  if (IsFunctionTypeParameter()) {
    ASSERT(IsFinalized());
    if (index() >= num_free_fun_type_params) {
      // Do not instantiate the function type parameter.
      // Get a replacement from the updated function type.
      ASSERT(function_type_mapping != nullptr);
      result = function_type_mapping->MapTypeParameter(*this);
      ASSERT(TypeParameter::Cast(result).index() ==
             index() - num_free_fun_type_params);
      ASSERT(TypeParameter::Cast(result).base() ==
             base() - num_free_fun_type_params);
      ASSERT(TypeParameter::Cast(result).nullability() == nullability());
      AbstractType& upper_bound = AbstractType::Handle(zone, bound());
      if (!upper_bound.IsInstantiated()) {
        upper_bound = upper_bound.InstantiateFrom(
            instantiator_type_arguments, function_type_arguments,
            num_free_fun_type_params, space, function_type_mapping,
            num_parent_type_args_adjustment);
      }
      if (upper_bound.ptr() == Type::NeverType()) {
        // Normalize 'X extends Never' to 'Never'.
        result = Type::NeverType();
      }
    } else if (function_type_arguments.IsNull()) {
      return Type::DynamicType();
    } else {
      result = function_type_arguments.TypeAt(index());
      substituted = true;
    }
  } else {
    ASSERT(IsClassTypeParameter());
    ASSERT(IsFinalized());
    if (instantiator_type_arguments.IsNull()) {
      return Type::DynamicType();
    }
    if (instantiator_type_arguments.Length() <= index()) {
      // InstantiateFrom can be invoked from a compilation pipeline with
      // mismatching type arguments vector. This can only happen for
      // a dynamically unreachable code - which compiler can't remove
      // statically for some reason.
      // To prevent crashes we return AbstractType::null(), understood by caller
      // (see AssertAssignableInstr::Canonicalize).
      return AbstractType::null();
    }
    result = instantiator_type_arguments.TypeAt(index());
    substituted = true;
    // Instantiating a class type parameter cannot result in a
    // function type parameter.
    // Bounds of class type parameters are ignored in the VM.
  }
  result = result.SetInstantiatedNullability(*this, space);
  if (substituted && (num_parent_type_args_adjustment != 0)) {
    // This type parameter is used inside a generic function type.
    // A type being substituted can have nested function types,
    // whose number of parent function type arguments should be adjusted
    // after the substitution.
    result = result.UpdateFunctionTypes(num_parent_type_args_adjustment,
                                        kAllFree, space, function_type_mapping);
  }
  // Canonicalization is not part of instantiation.
  return result.NormalizeFutureOrType(space);
}

AbstractTypePtr TypeParameter::UpdateFunctionTypes(
    intptr_t num_parent_type_args_adjustment,
    intptr_t num_free_fun_type_params,
    Heap::Space space,
    FunctionTypeMapping* function_type_mapping) const {
  ASSERT(IsFinalized());
  ASSERT(num_parent_type_args_adjustment >= 0);
  if (IsFunctionTypeParameter() && (index() >= num_free_fun_type_params)) {
    Zone* zone = Thread::Current()->zone();
    ASSERT(function_type_mapping != nullptr);
    const auto& new_tp = TypeParameter::Handle(
        zone, function_type_mapping->MapTypeParameter(*this));
    ASSERT(new_tp.base() == base() + num_parent_type_args_adjustment);
    ASSERT(new_tp.index() == index() + num_parent_type_args_adjustment);
    ASSERT(new_tp.nullability() == nullability());
    ASSERT(new_tp.IsFinalized());
    return new_tp.ptr();
  } else {
    return ptr();
  }
}

AbstractTypePtr TypeParameter::Canonicalize(Thread* thread) const {
  ASSERT(IsFinalized());
  Zone* zone = thread->zone();
  if (IsCanonical()) {
#ifdef DEBUG
    if (IsFunctionTypeParameter()) {
      ASSERT(FunctionType::Handle(zone, parameterized_function_type()).IsOld());
    }
#endif
    return this->ptr();
  }
  auto isolate_group = thread->isolate_group();
  ObjectStore* object_store = isolate_group->object_store();
  TypeParameter& type_parameter = TypeParameter::Handle(zone);
  {
    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
    CanonicalTypeParameterSet table(zone,
                                    object_store->canonical_type_parameters());
    type_parameter ^= table.GetOrNull(CanonicalTypeParameterKey(*this));
    if (type_parameter.IsNull()) {
      // Add this type parameter into the canonical table of type parameters.
      if (this->IsNew()) {
        type_parameter ^= Object::Clone(*this, Heap::kOld);
      } else {
        type_parameter = this->ptr();
      }
      ASSERT(type_parameter.IsOld());
      type_parameter.SetCanonical();  // Mark object as being canonical.
      bool present = table.Insert(type_parameter);
      ASSERT(!present);
    }
    object_store->set_canonical_type_parameters(table.Release());
  }
  return type_parameter.ptr();
}

void TypeParameter::PrintName(NameVisibility name_visibility,
                              BaseTextBuffer* printer) const {
  const TypeParameter& type_param = TypeParameter::Cast(*this);
  // Type parameter names are meaningless after canonicalization.
  printer->AddString(type_param.CanonicalNameCString());
  printer->AddString(NullabilitySuffix(name_visibility));
}

uword TypeParameter::ComputeHash() const {
  ASSERT(IsFinalized());
  uint32_t result = base();
  result = CombineHashes(result, index());
  result = CombineHashes(result, static_cast<uint32_t>(nullability()));
  if (IsFunctionTypeParameter()) {
    const FunctionType& func =
        FunctionType::Handle(parameterized_function_type());
    result = CombineHashes(result, func.packed_parameter_counts());
    result = CombineHashes(result, func.packed_type_parameter_counts());
  } else {
    ASSERT(IsClassTypeParameter());
    result = CombineHashes(result, parameterized_class_id());
  }
  result = FinalizeHash(result, kHashBits);
  SetHash(result);
  return result;
}

TypeParameterPtr TypeParameter::New() {
  return Object::Allocate<TypeParameter>(Heap::kOld);
}

TypeParameterPtr TypeParameter::New(const Object& owner,
                                    intptr_t base,
                                    intptr_t index,
                                    Nullability nullability) {
  ASSERT(owner.IsNull() || owner.IsClass() || owner.IsFunctionType());
  const bool is_function_type_parameter = owner.IsFunctionType();
  const uint32_t flags = UntaggedTypeParameter::IsFunctionTypeParameter::encode(
      is_function_type_parameter);
  Zone* Z = Thread::Current()->zone();
  const TypeParameter& result = TypeParameter::Handle(Z, TypeParameter::New());
  result.set_flags(flags);
  if (is_function_type_parameter) {
    result.set_owner(owner);
  } else {
    result.set_parameterized_class_id(owner.IsNull() ? kIllegalCid
                                                     : Class::Cast(owner).id());
  }
  result.set_base(base);
  result.set_index(index);
  result.SetHash(0);
  result.set_nullability(nullability);
  result.set_type_state(UntaggedAbstractType::kAllocated);

  result.InitializeTypeTestingStubNonAtomic(
      Code::Handle(Z, TypeTestingStubGenerator::DefaultCodeForType(result)));
  return result.ptr();
}

const char* TypeParameter::CanonicalNameCString(bool is_class_type_parameter,
                                                intptr_t base,
                                                intptr_t index) {
  Thread* thread = Thread::Current();
  ZoneTextBuffer printer(thread->zone());
  const char* base_fmt = is_class_type_parameter ? "C%" Pd : "F%" Pd;
  const char* index_fmt = is_class_type_parameter ? "X%" Pd : "Y%" Pd;
  if (base != 0) {
    printer.Printf(base_fmt, base);
  }
  printer.Printf(index_fmt, index - base);
  return printer.buffer();
}

const char* TypeParameter::ToCString() const {
  if (IsNull()) {
    return "TypeParameter: null";
  }
  Thread* thread = Thread::Current();
  ZoneTextBuffer printer(thread->zone());
  printer.Printf("TypeParameter: ");
  printer.AddString(CanonicalNameCString());
  printer.AddString(NullabilitySuffix(kInternalName));
  return printer.buffer();
}

const char* Number::ToCString() const {
  // Number is an interface. No instances of Number should exist.
  UNREACHABLE();
  return "Number";
}

const char* Integer::ToCString() const {
  // Integer is an interface. No instances of Integer should exist except null.
  ASSERT(IsNull());
  return "nullptr Integer";
}

IntegerPtr Integer::New(const String& str, Heap::Space space) {
  // We are not supposed to have integers represented as two byte strings.
  ASSERT(str.IsOneByteString());
  if (str.IsNull() || (str.Length() == 0)) {
    return Integer::null();
  }
  int64_t value = 0;
  const char* cstr = str.ToCString();
  if (!OS::StringToInt64(cstr, &value)) {
    // Out of range.
    return Integer::null();
  }
  return Integer::New(value, space);
}

IntegerPtr Integer::NewCanonical(const String& str) {
  // We are not supposed to have integers represented as two byte strings.
  ASSERT(str.IsOneByteString());
  int64_t value = 0;
  const char* cstr = str.ToCString();
  if (!OS::StringToInt64(cstr, &value)) {
    // Out of range.
    return Integer::null();
  }
  return NewCanonical(value);
}

IntegerPtr Integer::NewCanonical(int64_t value) {
  if (Smi::IsValid(value)) {
    return Smi::New(static_cast<intptr_t>(value));
  }
  return Mint::NewCanonical(value);
}

IntegerPtr Integer::New(int64_t value, Heap::Space space) {
  const bool is_smi = Smi::IsValid(value);
  if (is_smi) {
    return Smi::New(static_cast<intptr_t>(value));
  }
  return Mint::New(value, space);
}

IntegerPtr Integer::NewFromUint64(uint64_t value, Heap::Space space) {
  return Integer::New(static_cast<int64_t>(value), space);
}

bool Integer::IsValueInRange(uint64_t value) {
  return (value <= static_cast<uint64_t>(Mint::kMaxValue));
}

bool Integer::Equals(const Instance& other) const {
  // Integer is an abstract class.
  UNREACHABLE();
  return false;
}

int Integer::CompareWith(const Integer& other) const {
  int64_t a = Value();
  int64_t b = other.Value();
  if (a < b) {
    return -1;
  } else if (a > b) {
    return 1;
  } else {
    return 0;
  }
}

uint32_t Integer::CanonicalizeHash() const {
  return Multiply64Hash(Value());
}

const char* Integer::ToHexCString(Zone* zone) const {
  ASSERT(IsSmi() || IsMint());
  int64_t value = Value();
  if (value < 0) {
    return OS::SCreate(zone, "-0x%" PX64, -static_cast<uint64_t>(value));
  } else {
    return OS::SCreate(zone, "0x%" PX64, static_cast<uint64_t>(value));
  }
}

IntegerPtr Integer::ArithmeticOp(Token::Kind operation,
                                 const Integer& other,
                                 Heap::Space space) const {
  // In 32-bit mode, the result of any operation between two Smis will fit in a
  // 32-bit signed result, except the product of two Smis, which will be 64-bit.
  // In 64-bit mode, the result of any operation between two Smis will fit in a
  // 64-bit signed result, except the product of two Smis (see below).
  if (IsSmi() && other.IsSmi()) {
    const intptr_t left_value = Smi::Value(Smi::RawCast(ptr()));
    const intptr_t right_value = Smi::Value(Smi::RawCast(other.ptr()));
    switch (operation) {
      case Token::kADD:
        return Integer::New(left_value + right_value, space);
      case Token::kSUB:
        return Integer::New(left_value - right_value, space);
      case Token::kMUL:
        return Integer::New(
            Utils::MulWithWrapAround(static_cast<int64_t>(left_value),
                                     static_cast<int64_t>(right_value)),
            space);
      case Token::kTRUNCDIV:
        return Integer::New(left_value / right_value, space);
      case Token::kMOD: {
        const intptr_t remainder = left_value % right_value;
        if (remainder < 0) {
          if (right_value < 0) {
            return Integer::New(remainder - right_value, space);
          } else {
            return Integer::New(remainder + right_value, space);
          }
        }
        return Integer::New(remainder, space);
      }
      default:
        UNIMPLEMENTED();
    }
  }
  const int64_t left_value = Value();
  const int64_t right_value = other.Value();
  switch (operation) {
    case Token::kADD:
      return Integer::New(Utils::AddWithWrapAround(left_value, right_value),
                          space);

    case Token::kSUB:
      return Integer::New(Utils::SubWithWrapAround(left_value, right_value),
                          space);

    case Token::kMUL:
      return Integer::New(Utils::MulWithWrapAround(left_value, right_value),
                          space);

    case Token::kTRUNCDIV:
      if ((left_value == Mint::kMinValue) && (right_value == -1)) {
        // Division special case: overflow in int64_t.
        // MIN_VALUE / -1 = (MAX_VALUE + 1), which wraps around to MIN_VALUE
        return Integer::New(Mint::kMinValue, space);
      }
      return Integer::New(left_value / right_value, space);

    case Token::kMOD: {
      if ((left_value == Mint::kMinValue) && (right_value == -1)) {
        // Modulo special case: overflow in int64_t.
        // MIN_VALUE % -1 = 0 for reason given above.
        return Integer::New(0, space);
      }
      const int64_t remainder = left_value % right_value;
      if (remainder < 0) {
        if (right_value < 0) {
          return Integer::New(remainder - right_value, space);
        } else {
          return Integer::New(remainder + right_value, space);
        }
      }
      return Integer::New(remainder, space);
    }
    default:
      UNIMPLEMENTED();
      return Integer::null();
  }
}

IntegerPtr Integer::BitOp(Token::Kind kind,
                          const Integer& other,
                          Heap::Space space) const {
  if (IsSmi() && other.IsSmi()) {
    intptr_t op1_value = Smi::Value(Smi::RawCast(ptr()));
    intptr_t op2_value = Smi::Value(Smi::RawCast(other.ptr()));
    intptr_t result = 0;
    switch (kind) {
      case Token::kBIT_AND:
        result = op1_value & op2_value;
        break;
      case Token::kBIT_OR:
        result = op1_value | op2_value;
        break;
      case Token::kBIT_XOR:
        result = op1_value ^ op2_value;
        break;
      default:
        UNIMPLEMENTED();
    }
    ASSERT(Smi::IsValid(result));
    return Smi::New(result);
  } else {
    int64_t a = Value();
    int64_t b = other.Value();
    switch (kind) {
      case Token::kBIT_AND:
        return Integer::New(a & b, space);
      case Token::kBIT_OR:
        return Integer::New(a | b, space);
      case Token::kBIT_XOR:
        return Integer::New(a ^ b, space);
      default:
        UNIMPLEMENTED();
        return Integer::null();
    }
  }
}

IntegerPtr Integer::ShiftOp(Token::Kind kind,
                            const Integer& other,
                            Heap::Space space) const {
  int64_t a = Value();
  int64_t b = other.Value();
  ASSERT(b >= 0);
  switch (kind) {
    case Token::kSHL:
      return Integer::New(Utils::ShiftLeftWithTruncation(a, b), space);
    case Token::kSHR:
      return Integer::New(a >> Utils::Minimum<int64_t>(b, Mint::kBits), space);
    case Token::kUSHR:
      return Integer::New(
          (b >= kBitsPerInt64) ? 0 : static_cast<uint64_t>(a) >> b, space);
    default:
      UNIMPLEMENTED();
      return Integer::null();
  }
}

bool Smi::Equals(const Instance& other) const {
  if (other.IsNull() || !other.IsSmi()) {
    return false;
  }
  return (this->Value() == Smi::Cast(other).Value());
}

const char* Smi::ToCString() const {
  return OS::SCreate(Thread::Current()->zone(), "%" Pd "", Value());
}

ClassPtr Smi::Class() {
  return IsolateGroup::Current()->object_store()->smi_class();
}

void Mint::set_value(int64_t value) const {
  StoreNonPointer(&untag()->value_, value);
}

MintPtr Mint::New(int64_t val, Heap::Space space) {
  // Do not allocate a Mint if Smi would do.
  ASSERT(!Smi::IsValid(val));
  ASSERT(IsolateGroup::Current()->object_store()->mint_class() !=
         Class::null());
  const auto& result = Mint::Handle(Object::Allocate<Mint>(space));
  result.set_value(val);
  return result.ptr();
}

MintPtr Mint::NewCanonical(int64_t value) {
  Thread* thread = Thread::Current();
  Mint& mint = Mint::Handle(thread->zone(), Mint::New(value, Heap::kOld));
  mint ^= mint.Canonicalize(thread);
  return mint.ptr();
}

bool Mint::Equals(const Instance& other) const {
  if (this->ptr() == other.ptr()) {
    // Both handles point to the same raw instance.
    return true;
  }
  if (!other.IsMint() || other.IsNull()) {
    return false;
  }
  return Value() == Mint::Cast(other).Value();
}

const char* Mint::ToCString() const {
  return OS::SCreate(Thread::Current()->zone(), "%" Pd64 "", Value());
}

void Double::set_value(double value) const {
  StoreNonPointer(&untag()->value_, value);
}

bool Double::BitwiseEqualsToDouble(double value) const {
  intptr_t value_offset = Double::value_offset();
  void* this_addr = reinterpret_cast<void*>(
      reinterpret_cast<uword>(this->untag()) + value_offset);
  void* other_addr = reinterpret_cast<void*>(&value);
  return (memcmp(this_addr, other_addr, sizeof(value)) == 0);
}

bool Double::OperatorEquals(const Instance& other) const {
  if (this->IsNull() || other.IsNull()) {
    return (this->IsNull() && other.IsNull());
  }
  if (!other.IsDouble()) {
    return false;
  }
  return this->value() == Double::Cast(other).value();
}

bool Double::CanonicalizeEquals(const Instance& other) const {
  if (this->ptr() == other.ptr()) {
    return true;  // "===".
  }
  if (other.IsNull() || !other.IsDouble()) {
    return false;
  }
  return BitwiseEqualsToDouble(Double::Cast(other).value());
}

uint32_t Double::CanonicalizeHash() const {
  return Hash64To32(bit_cast<uint64_t>(value()));
}

DoublePtr Double::New(double d, Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->double_class() !=
         Class::null());
  const auto& result = Double::Handle(Object::Allocate<Double>(space));
  result.set_value(d);
  return result.ptr();
}

DoublePtr Double::New(const String& str, Heap::Space space) {
  double double_value;
  if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) {
    return Double::Handle().ptr();
  }
  return New(double_value, space);
}

DoublePtr Double::NewCanonical(double value) {
  Thread* thread = Thread::Current();
  Double& dbl = Double::Handle(thread->zone(), Double::New(value, Heap::kOld));
  dbl ^= dbl.Canonicalize(thread);
  return dbl.ptr();
}

DoublePtr Double::NewCanonical(const String& str) {
  double double_value;
  if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) {
    return Double::Handle().ptr();
  }
  return NewCanonical(double_value);
}

StringPtr Number::ToString(Heap::Space space) const {
  // Refactoring can avoid Zone::Alloc and strlen, but gains are insignificant.
  const char* cstr = ToCString();
  intptr_t len = strlen(cstr);
// Resulting string is ASCII ...
#ifdef DEBUG
  for (intptr_t i = 0; i < len; ++i) {
    ASSERT(static_cast<uint8_t>(cstr[i]) < 128);
  }
#endif  // DEBUG
  // ... which is a subset of Latin-1.
  return String::FromLatin1(reinterpret_cast<const uint8_t*>(cstr), len, space);
}

const char* Double::ToCString() const {
  if (isnan(value())) {
    return "NaN";
  }
  if (isinf(value())) {
    return value() < 0 ? "-Infinity" : "Infinity";
  }
  const int kBufferSize = 128;
  char* buffer = Thread::Current()->zone()->Alloc<char>(kBufferSize);
  buffer[kBufferSize - 1] = '\0';
  DoubleToCString(value(), buffer, kBufferSize);
  return buffer;
}

void StringHasher::Add(const String& str, intptr_t begin_index, intptr_t len) {
  ASSERT(begin_index >= 0);
  ASSERT(len >= 0);
  ASSERT((begin_index + len) <= str.Length());
  if (len == 0) {
    return;
  }
  if (str.IsOneByteString()) {
    NoSafepointScope no_safepoint;
    Add(OneByteString::CharAddr(str, begin_index), len);
  } else if (str.IsTwoByteString()) {
    NoSafepointScope no_safepoint;
    Add(TwoByteString::CharAddr(str, begin_index), len);
  } else {
    UNREACHABLE();
  }
}

uword String::Hash(const String& str, intptr_t begin_index, intptr_t len) {
  StringHasher hasher;
  hasher.Add(str, begin_index, len);
  return hasher.Finalize();
}

uword String::HashConcat(const String& str1, const String& str2) {
  StringHasher hasher;
  hasher.Add(str1, 0, str1.Length());
  hasher.Add(str2, 0, str2.Length());
  return hasher.Finalize();
}

uword String::Hash(StringPtr raw) {
  StringHasher hasher;
  uword length = Smi::Value(raw->untag()->length());
  if (raw->IsOneByteString()) {
    const uint8_t* data = static_cast<OneByteStringPtr>(raw)->untag()->data();
    return String::Hash(data, length);
  } else {
    const uint16_t* data = static_cast<TwoByteStringPtr>(raw)->untag()->data();
    return String::Hash(data, length);
  }
}

uword String::Hash(const char* characters, intptr_t len) {
  StringHasher hasher;
  hasher.Add(reinterpret_cast<const uint8_t*>(characters), len);
  return hasher.Finalize();
}

uword String::Hash(const uint8_t* characters, intptr_t len) {
  StringHasher hasher;
  hasher.Add(characters, len);
  return hasher.Finalize();
}

uword String::Hash(const uint16_t* characters, intptr_t len) {
  StringHasher hasher;
  hasher.Add(characters, len);
  return hasher.Finalize();
}

intptr_t String::CharSize() const {
  intptr_t class_id = ptr()->GetClassIdOfHeapObject();
  if (class_id == kOneByteStringCid) {
    return kOneByteChar;
  }
  ASSERT(class_id == kTwoByteStringCid);
  return kTwoByteChar;
}

bool String::Equals(const Instance& other) const {
  if (this->ptr() == other.ptr()) {
    // Both handles point to the same raw instance.
    return true;
  }

  if (!other.IsString()) {
    return false;
  }

  const String& other_string = String::Cast(other);
  return Equals(other_string);
}

bool String::Equals(const String& str,
                    intptr_t begin_index,
                    intptr_t len) const {
  ASSERT(begin_index >= 0);
  ASSERT((begin_index == 0) || (begin_index < str.Length()));
  ASSERT(len >= 0);
  ASSERT(len <= str.Length());
  if (len != this->Length()) {
    return false;  // Lengths don't match.
  }

  for (intptr_t i = 0; i < len; i++) {
    if (CharAt(i) != str.CharAt(begin_index + i)) {
      return false;
    }
  }

  return true;
}

bool String::Equals(const char* cstr) const {
  ASSERT(cstr != nullptr);
  CodePointIterator it(*this);
  intptr_t len = strlen(cstr);
  while (it.Next()) {
    if (*cstr == '\0') {
      // Lengths don't match.
      return false;
    }
    int32_t ch;
    intptr_t consumed =
        Utf8::Decode(reinterpret_cast<const uint8_t*>(cstr), len, &ch);
    if (consumed == 0 || it.Current() != ch) {
      return false;
    }
    cstr += consumed;
    len -= consumed;
  }
  return *cstr == '\0';
}

bool String::Equals(const uint8_t* latin1_array, intptr_t len) const {
  if (len != this->Length()) {
    // Lengths don't match.
    return false;
  }

  for (intptr_t i = 0; i < len; i++) {
    if (this->CharAt(i) != latin1_array[i]) {
      return false;
    }
  }
  return true;
}

bool String::Equals(const uint16_t* utf16_array, intptr_t len) const {
  if (len != this->Length()) {
    // Lengths don't match.
    return false;
  }

  for (intptr_t i = 0; i < len; i++) {
    if (this->CharAt(i) != LoadUnaligned(&utf16_array[i])) {
      return false;
    }
  }
  return true;
}

bool String::Equals(const int32_t* utf32_array, intptr_t len) const {
  if (len < 0) return false;
  intptr_t j = 0;
  for (intptr_t i = 0; i < len; ++i) {
    if (Utf::IsSupplementary(utf32_array[i])) {
      uint16_t encoded[2];
      Utf16::Encode(utf32_array[i], &encoded[0]);
      if (j + 1 >= Length()) return false;
      if (CharAt(j++) != encoded[0]) return false;
      if (CharAt(j++) != encoded[1]) return false;
    } else {
      if (j >= Length()) return false;
      if (CharAt(j++) != utf32_array[i]) return false;
    }
  }
  return j == Length();
}

bool String::EqualsConcat(const String& str1, const String& str2) const {
  return (Length() == str1.Length() + str2.Length()) &&
         str1.Equals(*this, 0, str1.Length()) &&
         str2.Equals(*this, str1.Length(), str2.Length());
}

intptr_t String::CompareTo(const String& other) const {
  const intptr_t this_len = this->Length();
  const intptr_t other_len = other.IsNull() ? 0 : other.Length();
  const intptr_t len = (this_len < other_len) ? this_len : other_len;
  for (intptr_t i = 0; i < len; i++) {
    uint16_t this_code_unit = this->CharAt(i);
    uint16_t other_code_unit = other.CharAt(i);
    if (this_code_unit < other_code_unit) {
      return -1;
    }
    if (this_code_unit > other_code_unit) {
      return 1;
    }
  }
  if (this_len < other_len) return -1;
  if (this_len > other_len) return 1;
  return 0;
}

bool String::StartsWith(StringPtr str, StringPtr prefix) {
  if (prefix == String::null()) return false;

  const intptr_t length = String::LengthOf(str);
  const intptr_t prefix_length = String::LengthOf(prefix);
  if (prefix_length > length) return false;

  for (intptr_t i = 0; i < prefix_length; i++) {
    if (String::CharAt(str, i) != String::CharAt(prefix, i)) {
      return false;
    }
  }
  return true;
}

bool String::EndsWith(const String& other) const {
  if (other.IsNull()) {
    return false;
  }
  const intptr_t len = this->Length();
  const intptr_t other_len = other.Length();
  const intptr_t offset = len - other_len;

  if ((other_len == 0) || (other_len > len)) {
    return false;
  }
  for (int i = offset; i < len; i++) {
    if (this->CharAt(i) != other.CharAt(i - offset)) {
      return false;
    }
  }
  return true;
}

InstancePtr String::CanonicalizeLocked(Thread* thread) const {
  if (IsCanonical()) {
    return this->ptr();
  }
  return Symbols::New(Thread::Current(), *this);
}

StringPtr String::New(const char* cstr, Heap::Space space) {
  ASSERT(cstr != nullptr);
  intptr_t array_len = strlen(cstr);
  const uint8_t* utf8_array = reinterpret_cast<const uint8_t*>(cstr);
  return String::FromUTF8(utf8_array, array_len, space);
}

StringPtr String::FromUTF8(const uint8_t* utf8_array,
                           intptr_t array_len,
                           Heap::Space space) {
  Utf8::Type type;
  intptr_t len = Utf8::CodeUnitCount(utf8_array, array_len, &type);
  if (type == Utf8::kLatin1) {
    const String& strobj = String::Handle(OneByteString::New(len, space));
    if (len > 0) {
      NoSafepointScope no_safepoint;
      if (!Utf8::DecodeToLatin1(utf8_array, array_len,
                                OneByteString::DataStart(strobj), len)) {
        Utf8::ReportInvalidByte(utf8_array, array_len, len);
        return String::null();
      }
    }
    return strobj.ptr();
  }
  ASSERT((type == Utf8::kBMP) || (type == Utf8::kSupplementary));
  const String& strobj = String::Handle(TwoByteString::New(len, space));
  NoSafepointScope no_safepoint;
  if (!Utf8::DecodeToUTF16(utf8_array, array_len,
                           TwoByteString::DataStart(strobj), len)) {
    Utf8::ReportInvalidByte(utf8_array, array_len, len);
    return String::null();
  }
  return strobj.ptr();
}

StringPtr String::FromLatin1(const uint8_t* latin1_array,
                             intptr_t array_len,
                             Heap::Space space) {
  return OneByteString::New(latin1_array, array_len, space);
}

StringPtr String::FromUTF16(const uint16_t* utf16_array,
                            intptr_t array_len,
                            Heap::Space space) {
  bool is_one_byte_string = true;
  for (intptr_t i = 0; i < array_len; ++i) {
    if (!Utf::IsLatin1(LoadUnaligned(&utf16_array[i]))) {
      is_one_byte_string = false;
      break;
    }
  }
  if (is_one_byte_string) {
    return OneByteString::New(utf16_array, array_len, space);
  }
  return TwoByteString::New(utf16_array, array_len, space);
}

StringPtr String::FromUTF32(const int32_t* utf32_array,
                            intptr_t array_len,
                            Heap::Space space) {
  bool is_one_byte_string = true;
  intptr_t utf16_len = array_len;
  for (intptr_t i = 0; i < array_len; ++i) {
    if (!Utf::IsLatin1(utf32_array[i])) {
      is_one_byte_string = false;
      if (Utf::IsSupplementary(utf32_array[i])) {
        utf16_len += 1;
      }
    }
  }
  if (is_one_byte_string) {
    return OneByteString::New(utf32_array, array_len, space);
  }
  return TwoByteString::New(utf16_len, utf32_array, array_len, space);
}

StringPtr String::New(const String& str, Heap::Space space) {
  // Currently this just creates a copy of the string in the correct space.
  // Once we have external string support, this will also create a heap copy of
  // the string if necessary. Some optimizations are possible, such as not
  // copying internal strings into the same space.
  intptr_t len = str.Length();
  String& result = String::Handle();
  intptr_t char_size = str.CharSize();
  if (char_size == kOneByteChar) {
    result = OneByteString::New(len, space);
  } else {
    ASSERT(char_size == kTwoByteChar);
    result = TwoByteString::New(len, space);
  }
  String::Copy(result, 0, str, 0, len);
  return result.ptr();
}

void String::Copy(const String& dst,
                  intptr_t dst_offset,
                  const uint8_t* characters,
                  intptr_t len) {
  ASSERT(dst_offset >= 0);
  ASSERT(len >= 0);
  ASSERT(len <= (dst.Length() - dst_offset));
  if (dst.IsOneByteString()) {
    NoSafepointScope no_safepoint;
    if (len > 0) {
      memmove(OneByteString::CharAddr(dst, dst_offset), characters, len);
    }
  } else if (dst.IsTwoByteString()) {
    for (intptr_t i = 0; i < len; ++i) {
      *TwoByteString::CharAddr(dst, i + dst_offset) = characters[i];
    }
  }
}

void String::Copy(const String& dst,
                  intptr_t dst_offset,
                  const uint16_t* utf16_array,
                  intptr_t array_len) {
  ASSERT(dst_offset >= 0);
  ASSERT(array_len >= 0);
  ASSERT(array_len <= (dst.Length() - dst_offset));
  if (dst.IsOneByteString()) {
    NoSafepointScope no_safepoint;
    for (intptr_t i = 0; i < array_len; ++i) {
      ASSERT(Utf::IsLatin1(LoadUnaligned(&utf16_array[i])));
      *OneByteString::CharAddr(dst, i + dst_offset) = utf16_array[i];
    }
  } else {
    ASSERT(dst.IsTwoByteString());
    NoSafepointScope no_safepoint;
    if (array_len > 0) {
      memmove(TwoByteString::CharAddr(dst, dst_offset), utf16_array,
              array_len * 2);
    }
  }
}

void String::Copy(const String& dst,
                  intptr_t dst_offset,
                  const String& src,
                  intptr_t src_offset,
                  intptr_t len) {
  ASSERT(dst_offset >= 0);
  ASSERT(src_offset >= 0);
  ASSERT(len >= 0);
  ASSERT(len <= (dst.Length() - dst_offset));
  ASSERT(len <= (src.Length() - src_offset));
  if (len > 0) {
    intptr_t char_size = src.CharSize();
    if (char_size == kOneByteChar) {
      ASSERT(src.IsOneByteString());
      NoSafepointScope no_safepoint;
      String::Copy(dst, dst_offset, OneByteString::CharAddr(src, src_offset),
                   len);
    } else {
      ASSERT(char_size == kTwoByteChar);
      ASSERT(src.IsTwoByteString());
      NoSafepointScope no_safepoint;
      String::Copy(dst, dst_offset, TwoByteString::CharAddr(src, src_offset),
                   len);
    }
  }
}

StringPtr String::EscapeSpecialCharacters(const String& str) {
  if (str.IsOneByteString()) {
    return OneByteString::EscapeSpecialCharacters(str);
  }
  ASSERT(str.IsTwoByteString());
  return TwoByteString::EscapeSpecialCharacters(str);
}

static bool IsPercent(int32_t c) {
  return c == '%';
}

static bool IsHexCharacter(int32_t c) {
  if (c >= '0' && c <= '9') {
    return true;
  }
  if (c >= 'A' && c <= 'F') {
    return true;
  }
  return false;
}

static bool IsURISafeCharacter(int32_t c) {
  if ((c >= '0') && (c <= '9')) {
    return true;
  }
  if ((c >= 'a') && (c <= 'z')) {
    return true;
  }
  if ((c >= 'A') && (c <= 'Z')) {
    return true;
  }
  return (c == '-') || (c == '_') || (c == '.') || (c == '~');
}

static int32_t GetHexCharacter(int32_t c) {
  ASSERT(c >= 0);
  ASSERT(c < 16);
  const char* hex = "0123456789ABCDEF";
  return hex[c];
}

static int32_t GetHexValue(int32_t c) {
  if (c >= '0' && c <= '9') {
    return c - '0';
  }
  if (c >= 'A' && c <= 'F') {
    return c - 'A' + 10;
  }
  UNREACHABLE();
  return 0;
}

static int32_t MergeHexCharacters(int32_t c1, int32_t c2) {
  return GetHexValue(c1) << 4 | GetHexValue(c2);
}

const char* String::EncodeIRI(const String& str) {
  const intptr_t len = Utf8::Length(str);
  Zone* zone = Thread::Current()->zone();
  uint8_t* utf8 = zone->Alloc<uint8_t>(len);
  str.ToUTF8(utf8, len);
  intptr_t num_escapes = 0;
  for (int i = 0; i < len; ++i) {
    uint8_t byte = utf8[i];
    if (!IsURISafeCharacter(byte)) {
      num_escapes += 2;
    }
  }
  intptr_t cstr_len = len + num_escapes + 1;
  char* cstr = zone->Alloc<char>(cstr_len);
  intptr_t index = 0;
  for (int i = 0; i < len; ++i) {
    uint8_t byte = utf8[i];
    if (!IsURISafeCharacter(byte)) {
      cstr[index++] = '%';
      cstr[index++] = GetHexCharacter(byte >> 4);
      cstr[index++] = GetHexCharacter(byte & 0xF);
    } else {
      ASSERT(byte <= 127);
      cstr[index++] = byte;
    }
  }
  cstr[index] = '\0';
  return cstr;
}

StringPtr String::DecodeIRI(const String& str) {
  CodePointIterator cpi(str);
  intptr_t num_escapes = 0;
  intptr_t len = str.Length();
  {
    CodePointIterator cpi(str);
    while (cpi.Next()) {
      int32_t code_point = cpi.Current();
      if (IsPercent(code_point)) {
        // Verify that the two characters following the % are hex digits.
        if (!cpi.Next()) {
          return String::null();
        }
        int32_t code_point = cpi.Current();
        if (!IsHexCharacter(code_point)) {
          return String::null();
        }
        if (!cpi.Next()) {
          return String::null();
        }
        code_point = cpi.Current();
        if (!IsHexCharacter(code_point)) {
          return String::null();
        }
        num_escapes += 2;
      }
    }
  }
  intptr_t utf8_len = len - num_escapes;
  ASSERT(utf8_len >= 0);
  Zone* zone = Thread::Current()->zone();
  uint8_t* utf8 = zone->Alloc<uint8_t>(utf8_len);
  {
    intptr_t index = 0;
    CodePointIterator cpi(str);
    while (cpi.Next()) {
      ASSERT(index < utf8_len);
      int32_t code_point = cpi.Current();
      if (IsPercent(code_point)) {
        cpi.Next();
        int32_t ch1 = cpi.Current();
        cpi.Next();
        int32_t ch2 = cpi.Current();
        int32_t merged = MergeHexCharacters(ch1, ch2);
        ASSERT(merged >= 0 && merged < 256);
        utf8[index] = static_cast<uint8_t>(merged);
      } else {
        ASSERT(code_point >= 0 && code_point < 256);
        utf8[index] = static_cast<uint8_t>(code_point);
      }
      index++;
    }
  }
  return FromUTF8(utf8, utf8_len);
}

StringPtr String::NewFormatted(const char* format, ...) {
  va_list args;
  va_start(args, format);
  StringPtr result = NewFormattedV(format, args);
  NoSafepointScope no_safepoint;
  va_end(args);
  return result;
}

StringPtr String::NewFormatted(Heap::Space space, const char* format, ...) {
  va_list args;
  va_start(args, format);
  StringPtr result = NewFormattedV(format, args, space);
  NoSafepointScope no_safepoint;
  va_end(args);
  return result;
}

StringPtr String::NewFormattedV(const char* format,
                                va_list args,
                                Heap::Space space) {
  va_list args_copy;
  va_copy(args_copy, args);
  intptr_t len = Utils::VSNPrint(nullptr, 0, format, args_copy);
  va_end(args_copy);

  Zone* zone = Thread::Current()->zone();
  char* buffer = zone->Alloc<char>(len + 1);
  Utils::VSNPrint(buffer, (len + 1), format, args);

  return String::New(buffer, space);
}

StringPtr String::Concat(const String& str1,
                         const String& str2,
                         Heap::Space space) {
  ASSERT(!str1.IsNull() && !str2.IsNull());
  intptr_t char_size = Utils::Maximum(str1.CharSize(), str2.CharSize());
  if (char_size == kTwoByteChar) {
    return TwoByteString::Concat(str1, str2, space);
  }
  return OneByteString::Concat(str1, str2, space);
}

StringPtr String::ConcatAll(const Array& strings, Heap::Space space) {
  return ConcatAllRange(strings, 0, strings.Length(), space);
}

StringPtr String::ConcatAllRange(const Array& strings,
                                 intptr_t start,
                                 intptr_t end,
                                 Heap::Space space) {
  ASSERT(!strings.IsNull());
  ASSERT(start >= 0);
  ASSERT(end <= strings.Length());
  intptr_t result_len = 0;
  String& str = String::Handle();
  intptr_t char_size = kOneByteChar;
  // Compute 'char_size' and 'result_len'.
  for (intptr_t i = start; i < end; i++) {
    str ^= strings.At(i);
    const intptr_t str_len = str.Length();
    if ((kMaxElements - result_len) < str_len) {
      Exceptions::ThrowOOM();
      UNREACHABLE();
    }
    result_len += str_len;
    char_size = Utils::Maximum(char_size, str.CharSize());
  }
  if (char_size == kOneByteChar) {
    return OneByteString::ConcatAll(strings, start, end, result_len, space);
  }
  ASSERT(char_size == kTwoByteChar);
  return TwoByteString::ConcatAll(strings, start, end, result_len, space);
}

StringPtr String::SubString(const String& str,
                            intptr_t begin_index,
                            Heap::Space space) {
  ASSERT(!str.IsNull());
  if (begin_index >= str.Length()) {
    return String::null();
  }
  return String::SubString(str, begin_index, (str.Length() - begin_index),
                           space);
}

StringPtr String::SubString(Thread* thread,
                            const String& str,
                            intptr_t begin_index,
                            intptr_t length,
                            Heap::Space space) {
  ASSERT(!str.IsNull());
  ASSERT(begin_index >= 0);
  ASSERT(length >= 0);
  if (begin_index <= str.Length() && length == 0) {
    return Symbols::Empty().ptr();
  }
  if (begin_index > str.Length()) {
    return String::null();
  }
  bool is_one_byte_string = true;
  intptr_t char_size = str.CharSize();
  if (char_size == kTwoByteChar) {
    for (intptr_t i = begin_index; i < begin_index + length; ++i) {
      if (!Utf::IsLatin1(str.CharAt(i))) {
        is_one_byte_string = false;
        break;
      }
    }
  }
  REUSABLE_STRING_HANDLESCOPE(thread);
  String& result = thread->StringHandle();
  if (is_one_byte_string) {
    result = OneByteString::New(length, space);
  } else {
    result = TwoByteString::New(length, space);
  }
  String::Copy(result, 0, str, begin_index, length);
  return result.ptr();
}

const char* String::ToCString() const {
  if (IsNull()) {
    return "String: null";
  }
  const intptr_t len = Utf8::Length(*this);
  Zone* zone = Thread::Current()->zone();
  uint8_t* result = zone->Alloc<uint8_t>(len + 1);
  ToUTF8(result, len);
  result[len] = 0;
  return reinterpret_cast<const char*>(result);
}

char* String::ToMallocCString() const {
  const intptr_t len = Utf8::Length(*this);
  uint8_t* result = reinterpret_cast<uint8_t*>(malloc(len + 1));
  ToUTF8(result, len);
  result[len] = 0;
  return reinterpret_cast<char*>(result);
}

void String::ToUTF8(uint8_t* utf8_array, intptr_t array_len) const {
  ASSERT(array_len >= Utf8::Length(*this));
  Utf8::Encode(*this, reinterpret_cast<char*>(utf8_array), array_len);
}

const char* String::ToCString(Thread* thread, StringPtr ptr) {
  if (ptr == nullptr) return nullptr;
  REUSABLE_STRING_HANDLESCOPE(thread);
  String& str = reused_string_handle.Handle();
  str = ptr;
  return str.ToCString();
}

static FinalizablePersistentHandle* AddFinalizer(const Object& referent,
                                                 void* peer,
                                                 Dart_HandleFinalizer callback,
                                                 intptr_t external_size) {
  ASSERT(callback != nullptr);
  FinalizablePersistentHandle* finalizable_ref =
      FinalizablePersistentHandle::New(IsolateGroup::Current(), referent, peer,
                                       callback, external_size,
                                       /*auto_delete=*/true);
  ASSERT(finalizable_ref != nullptr);
  return finalizable_ref;
}

StringPtr String::Transform(int32_t (*mapping)(int32_t ch),
                            const String& str,
                            Heap::Space space) {
  ASSERT(!str.IsNull());
  bool has_mapping = false;
  int32_t dst_max = 0;
  CodePointIterator it(str);
  while (it.Next()) {
    int32_t src = it.Current();
    int32_t dst = mapping(src);
    if (src != dst) {
      has_mapping = true;
    }
    dst_max = Utils::Maximum(dst_max, dst);
  }
  if (!has_mapping) {
    return str.ptr();
  }
  if (Utf::IsLatin1(dst_max)) {
    return OneByteString::Transform(mapping, str, space);
  }
  ASSERT(Utf::IsBmp(dst_max) || Utf::IsSupplementary(dst_max));
  return TwoByteString::Transform(mapping, str, space);
}

StringPtr String::ToUpperCase(const String& str, Heap::Space space) {
  // TODO(cshapiro): create a fast-path for OneByteString instances.
  return Transform(CaseMapping::ToUpper, str, space);
}

StringPtr String::ToLowerCase(const String& str, Heap::Space space) {
  // TODO(cshapiro): create a fast-path for OneByteString instances.
  return Transform(CaseMapping::ToLower, str, space);
}

bool String::ParseDouble(const String& str,
                         intptr_t start,
                         intptr_t end,
                         double* result) {
  ASSERT(0 <= start);
  ASSERT(start <= end);
  ASSERT(end <= str.Length());
  intptr_t length = end - start;
  NoSafepointScope no_safepoint;
  const uint8_t* startChar;
  if (str.IsOneByteString()) {
    startChar = OneByteString::CharAddr(str, start);
  } else {
    uint8_t* chars = Thread::Current()->zone()->Alloc<uint8_t>(length);
    for (intptr_t i = 0; i < length; i++) {
      int32_t ch = str.CharAt(start + i);
      if (ch < 128) {
        chars[i] = ch;
      } else {
        return false;  // Not ASCII, so definitely not valid double numeral.
      }
    }
    startChar = chars;
  }
  return CStringToDouble(reinterpret_cast<const char*>(startChar), length,
                         result);
}

// Check to see if 'str1' matches 'str2' as is or
// once the private key separator is stripped from str2.
//
// Things are made more complicated by the fact that constructors are
// added *after* the private suffix, so "foo@123.named" should match
// "foo.named".
//
// Also, the private suffix can occur more than once in the name, as in:
//
//    _ReceivePortImpl@6be832b._internal@6be832b
//
template <typename T1, typename T2>
static bool EqualsIgnoringPrivateKey(const String& str1, const String& str2) {
  intptr_t len = str1.Length();
  intptr_t str2_len = str2.Length();
  if (len == str2_len) {
    for (intptr_t i = 0; i < len; i++) {
      if (T1::CharAt(str1, i) != T2::CharAt(str2, i)) {
        return false;
      }
    }
    return true;
  }
  if (len < str2_len) {
    return false;  // No way they can match.
  }
  intptr_t pos = 0;
  intptr_t str2_pos = 0;
  while (pos < len) {
    int32_t ch = T1::CharAt(str1, pos);
    pos++;

    if ((str2_pos < str2_len) && (ch == T2::CharAt(str2, str2_pos))) {
      str2_pos++;
      continue;
    }

    if (ch == Library::kPrivateKeySeparator) {
      // Consume a private key separator if str1 has it but str2 does not.
      while ((pos < len) && (T1::CharAt(str1, pos) != '.') &&
             (T1::CharAt(str1, pos) != '&')) {
        pos++;
      }
      // Resume matching characters.
      continue;
    }

    return false;
  }

  // We have reached the end of mangled_name string.
  ASSERT(pos == len);
  return (str2_pos == str2_len);
}

#define EQUALS_IGNORING_PRIVATE_KEY(class_id, type, str1, str2)                \
  switch (class_id) {                                                          \
    case kOneByteStringCid:                                                    \
      return dart::EqualsIgnoringPrivateKey<type, OneByteString>(str1, str2);  \
    case kTwoByteStringCid:                                                    \
      return dart::EqualsIgnoringPrivateKey<type, TwoByteString>(str1, str2);  \
  }                                                                            \
  UNREACHABLE();

bool String::EqualsIgnoringPrivateKey(const String& str1, const String& str2) {
  if (str1.ptr() == str2.ptr()) {
    return true;  // Both handles point to the same raw instance.
  }
  NoSafepointScope no_safepoint;
  intptr_t str1_class_id = str1.ptr()->GetClassIdOfHeapObject();
  intptr_t str2_class_id = str2.ptr()->GetClassIdOfHeapObject();
  switch (str1_class_id) {
    case kOneByteStringCid:
      EQUALS_IGNORING_PRIVATE_KEY(str2_class_id, OneByteString, str1, str2);
      break;
    case kTwoByteStringCid:
      EQUALS_IGNORING_PRIVATE_KEY(str2_class_id, TwoByteString, str1, str2);
      break;
  }
  UNREACHABLE();
  return false;
}

bool String::CodePointIterator::Next() {
  ASSERT(index_ >= -1);
  intptr_t length = Utf16::Length(ch_);
  if (index_ < (end_ - length)) {
    index_ += length;
    ch_ = str_.CharAt(index_);
    if (Utf16::IsLeadSurrogate(ch_) && (index_ < (end_ - 1))) {
      int32_t ch2 = str_.CharAt(index_ + 1);
      if (Utf16::IsTrailSurrogate(ch2)) {
        ch_ = Utf16::Decode(ch_, ch2);
      }
    }
    return true;
  }
  index_ = end_;
  return false;
}

OneByteStringPtr OneByteString::EscapeSpecialCharacters(const String& str) {
  intptr_t len = str.Length();
  if (len > 0) {
    intptr_t num_escapes = 0;
    for (intptr_t i = 0; i < len; i++) {
      num_escapes += EscapeOverhead(CharAt(str, i));
    }
    const String& dststr =
        String::Handle(OneByteString::New(len + num_escapes, Heap::kNew));
    intptr_t index = 0;
    for (intptr_t i = 0; i < len; i++) {
      uint8_t ch = CharAt(str, i);
      if (IsSpecialCharacter(ch)) {
        SetCharAt(dststr, index, '\\');
        SetCharAt(dststr, index + 1, SpecialCharacter(ch));
        index += 2;
      } else if (IsAsciiNonprintable(ch)) {
        SetCharAt(dststr, index, '\\');
        SetCharAt(dststr, index + 1, 'x');
        SetCharAt(dststr, index + 2, GetHexCharacter(ch >> 4));
        SetCharAt(dststr, index + 3, GetHexCharacter(ch & 0xF));
        index += 4;
      } else {
        SetCharAt(dststr, index, ch);
        index += 1;
      }
    }
    return OneByteString::raw(dststr);
  }
  return OneByteString::raw(Symbols::Empty());
}

OneByteStringPtr OneByteString::New(intptr_t len, Heap::Space space) {
  ASSERT((IsolateGroup::Current() == Dart::vm_isolate_group()) ||
         ((IsolateGroup::Current()->object_store() != nullptr) &&
          (IsolateGroup::Current()->object_store()->one_byte_string_class() !=
           Class::null())));
  if (len < 0 || len > kMaxElements) {
    // This should be caught before we reach here.
    FATAL("Fatal error in OneByteString::New: invalid len %" Pd "\n", len);
  }
  auto result = Object::Allocate<OneByteString>(space, len);
  NoSafepointScope no_safepoint;
  result->untag()->set_length(Smi::New(len));
#if !defined(HASH_IN_OBJECT_HEADER)
  result->untag()->set_hash(Smi::New(0));
#endif
  intptr_t size = OneByteString::UnroundedSize(result);
  ASSERT(size <= result->untag()->HeapSize());
  memset(reinterpret_cast<void*>(UntaggedObject::ToAddr(result) + size), 0,
         result->untag()->HeapSize() - size);
  return result;
}

OneByteStringPtr OneByteString::New(const uint8_t* characters,
                                    intptr_t len,
                                    Heap::Space space) {
  const String& result = String::Handle(OneByteString::New(len, space));
  if (len > 0) {
    NoSafepointScope no_safepoint;
    memmove(DataStart(result), characters, len);
  }
  return OneByteString::raw(result);
}

OneByteStringPtr OneByteString::New(const uint16_t* characters,
                                    intptr_t len,
                                    Heap::Space space) {
  const String& result = String::Handle(OneByteString::New(len, space));
  NoSafepointScope no_safepoint;
  for (intptr_t i = 0; i < len; ++i) {
    ASSERT(Utf::IsLatin1(characters[i]));
    *CharAddr(result, i) = characters[i];
  }
  return OneByteString::raw(result);
}

OneByteStringPtr OneByteString::New(const int32_t* characters,
                                    intptr_t len,
                                    Heap::Space space) {
  const String& result = String::Handle(OneByteString::New(len, space));
  NoSafepointScope no_safepoint;
  for (intptr_t i = 0; i < len; ++i) {
    ASSERT(Utf::IsLatin1(characters[i]));
    *CharAddr(result, i) = characters[i];
  }
  return OneByteString::raw(result);
}

OneByteStringPtr OneByteString::New(const String& str, Heap::Space space) {
  intptr_t len = str.Length();
  const String& result = String::Handle(OneByteString::New(len, space));
  String::Copy(result, 0, str, 0, len);
  return OneByteString::raw(result);
}

OneByteStringPtr OneByteString::New(const String& other_one_byte_string,
                                    intptr_t other_start_index,
                                    intptr_t other_len,
                                    Heap::Space space) {
  const String& result = String::Handle(OneByteString::New(other_len, space));
  ASSERT(other_one_byte_string.IsOneByteString());
  if (other_len > 0) {
    NoSafepointScope no_safepoint;
    memmove(OneByteString::DataStart(result),
            OneByteString::CharAddr(other_one_byte_string, other_start_index),
            other_len);
  }
  return OneByteString::raw(result);
}

OneByteStringPtr OneByteString::New(const TypedDataBase& other_typed_data,
                                    intptr_t other_start_index,
                                    intptr_t other_len,
                                    Heap::Space space) {
  const String& result = String::Handle(OneByteString::New(other_len, space));
  ASSERT(other_typed_data.ElementSizeInBytes() == 1);
  if (other_len > 0) {
    NoSafepointScope no_safepoint;
    memmove(OneByteString::DataStart(result),
            other_typed_data.DataAddr(other_start_index), other_len);
  }
  return OneByteString::raw(result);
}

OneByteStringPtr OneByteString::Concat(const String& str1,
                                       const String& str2,
                                       Heap::Space space) {
  intptr_t len1 = str1.Length();
  intptr_t len2 = str2.Length();
  intptr_t len = len1 + len2;
  const String& result = String::Handle(OneByteString::New(len, space));
  String::Copy(result, 0, str1, 0, len1);
  String::Copy(result, len1, str2, 0, len2);
  return OneByteString::raw(result);
}

OneByteStringPtr OneByteString::ConcatAll(const Array& strings,
                                          intptr_t start,
                                          intptr_t end,
                                          intptr_t len,
                                          Heap::Space space) {
  ASSERT(!strings.IsNull());
  ASSERT(start >= 0);
  ASSERT(end <= strings.Length());
  const String& result = String::Handle(OneByteString::New(len, space));
  String& str = String::Handle();
  intptr_t pos = 0;
  for (intptr_t i = start; i < end; i++) {
    str ^= strings.At(i);
    const intptr_t str_len = str.Length();
    String::Copy(result, pos, str, 0, str_len);
    ASSERT((kMaxElements - pos) >= str_len);
    pos += str_len;
  }
  return OneByteString::raw(result);
}

OneByteStringPtr OneByteString::Transform(int32_t (*mapping)(int32_t ch),
                                          const String& str,
                                          Heap::Space space) {
  ASSERT(!str.IsNull());
  intptr_t len = str.Length();
  const String& result = String::Handle(OneByteString::New(len, space));
  NoSafepointScope no_safepoint;
  for (intptr_t i = 0; i < len; ++i) {
    int32_t ch = mapping(str.CharAt(i));
    ASSERT(Utf::IsLatin1(ch));
    *CharAddr(result, i) = ch;
  }
  return OneByteString::raw(result);
}

OneByteStringPtr OneByteString::SubStringUnchecked(const String& str,
                                                   intptr_t begin_index,
                                                   intptr_t length,
                                                   Heap::Space space) {
  ASSERT(!str.IsNull() && str.IsOneByteString());
  ASSERT(begin_index >= 0);
  ASSERT(length >= 0);
  if (begin_index <= str.Length() && length == 0) {
    return OneByteString::raw(Symbols::Empty());
  }
  ASSERT(begin_index < str.Length());
  OneByteStringPtr result = OneByteString::New(length, space);
  NoSafepointScope no_safepoint;
  if (length > 0) {
    uint8_t* dest = &result->untag()->data()[0];
    const uint8_t* src = &untag(str)->data()[begin_index];
    memmove(dest, src, length);
  }
  return result;
}

TwoByteStringPtr TwoByteString::EscapeSpecialCharacters(const String& str) {
  intptr_t len = str.Length();
  if (len > 0) {
    intptr_t num_escapes = 0;
    for (intptr_t i = 0; i < len; i++) {
      num_escapes += EscapeOverhead(CharAt(str, i));
    }
    const String& dststr =
        String::Handle(TwoByteString::New(len + num_escapes, Heap::kNew));
    intptr_t index = 0;
    for (intptr_t i = 0; i < len; i++) {
      uint16_t ch = CharAt(str, i);
      if (IsSpecialCharacter(ch)) {
        SetCharAt(dststr, index, '\\');
        SetCharAt(dststr, index + 1, SpecialCharacter(ch));
        index += 2;
      } else if (IsAsciiNonprintable(ch)) {
        SetCharAt(dststr, index, '\\');
        SetCharAt(dststr, index + 1, 'x');
        SetCharAt(dststr, index + 2, GetHexCharacter(ch >> 4));
        SetCharAt(dststr, index + 3, GetHexCharacter(ch & 0xF));
        index += 4;
      } else {
        SetCharAt(dststr, index, ch);
        index += 1;
      }
    }
    return TwoByteString::raw(dststr);
  }
  return TwoByteString::New(0, Heap::kNew);
}

TwoByteStringPtr TwoByteString::New(intptr_t len, Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->two_byte_string_class() !=
         nullptr);
  if (len < 0 || len > kMaxElements) {
    // This should be caught before we reach here.
    FATAL("Fatal error in TwoByteString::New: invalid len %" Pd "\n", len);
  }
  auto s = Object::Allocate<TwoByteString>(space, len);
  NoSafepointScope no_safepoint;
  s->untag()->set_length(Smi::New(len));
#if !defined(HASH_IN_OBJECT_HEADER)
  s->untag()->set_hash(Smi::New(0));
#endif
  intptr_t size = TwoByteString::UnroundedSize(s);
  ASSERT(size <= s->untag()->HeapSize());
  memset(reinterpret_cast<void*>(UntaggedObject::ToAddr(s) + size), 0,
         s->untag()->HeapSize() - size);
  return s;
}

TwoByteStringPtr TwoByteString::New(const uint16_t* utf16_array,
                                    intptr_t array_len,
                                    Heap::Space space) {
  ASSERT(array_len > 0);
  const String& result = String::Handle(TwoByteString::New(array_len, space));
  {
    NoSafepointScope no_safepoint;
    memmove(reinterpret_cast<void*>(DataStart(result)),
            reinterpret_cast<const void*>(utf16_array), (array_len * 2));
  }
  return TwoByteString::raw(result);
}

TwoByteStringPtr TwoByteString::New(intptr_t utf16_len,
                                    const int32_t* utf32_array,
                                    intptr_t array_len,
                                    Heap::Space space) {
  ASSERT((array_len > 0) && (utf16_len >= array_len));
  const String& result = String::Handle(TwoByteString::New(utf16_len, space));
  {
    NoSafepointScope no_safepoint;
    intptr_t j = 0;
    for (intptr_t i = 0; i < array_len; ++i) {
      if (Utf::IsSupplementary(utf32_array[i])) {
        ASSERT(j < (utf16_len - 1));
        Utf16::Encode(utf32_array[i], CharAddr(result, j));
        j += 2;
      } else {
        ASSERT(j < utf16_len);
        *CharAddr(result, j) = utf32_array[i];
        j += 1;
      }
    }
  }
  return TwoByteString::raw(result);
}

TwoByteStringPtr TwoByteString::New(const String& str, Heap::Space space) {
  intptr_t len = str.Length();
  const String& result = String::Handle(TwoByteString::New(len, space));
  String::Copy(result, 0, str, 0, len);
  return TwoByteString::raw(result);
}

TwoByteStringPtr TwoByteString::New(const TypedDataBase& other_typed_data,
                                    intptr_t other_start_index,
                                    intptr_t other_len,
                                    Heap::Space space) {
  const String& result = String::Handle(TwoByteString::New(other_len, space));
  if (other_len > 0) {
    NoSafepointScope no_safepoint;
    memmove(TwoByteString::DataStart(result),
            other_typed_data.DataAddr(other_start_index),
            other_len * sizeof(uint16_t));
  }
  return TwoByteString::raw(result);
}

TwoByteStringPtr TwoByteString::Concat(const String& str1,
                                       const String& str2,
                                       Heap::Space space) {
  intptr_t len1 = str1.Length();
  intptr_t len2 = str2.Length();
  intptr_t len = len1 + len2;
  const String& result = String::Handle(TwoByteString::New(len, space));
  String::Copy(result, 0, str1, 0, len1);
  String::Copy(result, len1, str2, 0, len2);
  return TwoByteString::raw(result);
}

TwoByteStringPtr TwoByteString::ConcatAll(const Array& strings,
                                          intptr_t start,
                                          intptr_t end,
                                          intptr_t len,
                                          Heap::Space space) {
  ASSERT(!strings.IsNull());
  ASSERT(start >= 0);
  ASSERT(end <= strings.Length());
  const String& result = String::Handle(TwoByteString::New(len, space));
  String& str = String::Handle();
  intptr_t pos = 0;
  for (intptr_t i = start; i < end; i++) {
    str ^= strings.At(i);
    const intptr_t str_len = str.Length();
    String::Copy(result, pos, str, 0, str_len);
    ASSERT((kMaxElements - pos) >= str_len);
    pos += str_len;
  }
  return TwoByteString::raw(result);
}

TwoByteStringPtr TwoByteString::Transform(int32_t (*mapping)(int32_t ch),
                                          const String& str,
                                          Heap::Space space) {
  ASSERT(!str.IsNull());
  intptr_t len = str.Length();
  const String& result = String::Handle(TwoByteString::New(len, space));
  String::CodePointIterator it(str);
  intptr_t i = 0;
  NoSafepointScope no_safepoint;
  while (it.Next()) {
    int32_t src = it.Current();
    int32_t dst = mapping(src);
    ASSERT(dst >= 0 && dst <= 0x10FFFF);
    intptr_t len = Utf16::Length(dst);
    if (len == 1) {
      *CharAddr(result, i) = dst;
    } else {
      ASSERT(len == 2);
      Utf16::Encode(dst, CharAddr(result, i));
    }
    i += len;
  }
  return TwoByteString::raw(result);
}

const char* Bool::ToCString() const {
  return value() ? "true" : "false";
}

bool Array::CanonicalizeEquals(const Instance& other) const {
  if (this->ptr() == other.ptr()) {
    // Both handles point to the same raw instance.
    return true;
  }

  // An Array may be compared to an ImmutableArray.
  if (!other.IsArray() || other.IsNull()) {
    return false;
  }

  // First check if both arrays have the same length and elements.
  const Array& other_arr = Array::Cast(other);

  intptr_t len = this->Length();
  if (len != other_arr.Length()) {
    return false;
  }

  for (intptr_t i = 0; i < len; i++) {
    if (this->At(i) != other_arr.At(i)) {
      return false;
    }
  }

  // Now check if both arrays have the same type arguments.
  if (GetTypeArguments() == other.GetTypeArguments()) {
    return true;
  }
  const TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
  const TypeArguments& other_type_args =
      TypeArguments::Handle(other.GetTypeArguments());
  if (!type_args.Equals(other_type_args)) {
    return false;
  }
  return true;
}

uint32_t Array::CanonicalizeHash() const {
  intptr_t len = Length();
  if (len == 0) {
    return 1;
  }
  Thread* thread = Thread::Current();
  uint32_t hash = thread->heap()->GetCanonicalHash(ptr());
  if (hash != 0) {
    return hash;
  }
  hash = len;
  Instance& member = Instance::Handle(GetTypeArguments());
  hash = CombineHashes(hash, member.CanonicalizeHash());
  for (intptr_t i = 0; i < len; i++) {
    member ^= At(i);
    hash = CombineHashes(hash, member.CanonicalizeHash());
  }
  hash = FinalizeHash(hash, kHashBits);
  thread->heap()->SetCanonicalHash(ptr(), hash);
  return hash;
}

ArrayPtr Array::New(intptr_t len,
                    const AbstractType& element_type,
                    Heap::Space space) {
  const Array& result = Array::Handle(Array::New(len, space));
  if (!element_type.IsDynamicType()) {
    TypeArguments& type_args = TypeArguments::Handle(TypeArguments::New(1));
    type_args.SetTypeAt(0, element_type);
    type_args = type_args.Canonicalize(Thread::Current());
    result.SetTypeArguments(type_args);
  }
  return result.ptr();
}

ArrayPtr Array::NewUninitialized(intptr_t class_id,
                                 intptr_t len,
                                 Heap::Space space) {
  if (!IsValidLength(len)) {
    // This should be caught before we reach here.
    FATAL("Fatal error in Array::New: invalid len %" Pd "\n", len);
  }
  auto raw = Object::AllocateVariant<Array>(class_id, space, len);
  NoSafepointScope no_safepoint;
  raw->untag()->set_length(Smi::New(len));
  if (UseCardMarkingForAllocation(len)) {
    ASSERT(raw->IsOldObject());
    raw->untag()->SetCardRememberedBitUnsynchronized();
    Page::Of(raw)->AllocateCardTable();
  }
  return raw;
}

ArrayPtr Array::New(intptr_t class_id, intptr_t len, Heap::Space space) {
  if (!UseCardMarkingForAllocation(len)) {
    return NewUninitialized(class_id, len, space);
  }

  Thread* thread = Thread::Current();
  Array& result =
      Array::Handle(thread->zone(), NewUninitialized(class_id, len, space));
  result.SetTypeArguments(Object::null_type_arguments());
  for (intptr_t i = 0; i < len; i++) {
    result.SetAt(i, Object::null_object(), thread);
    if (((i + 1) % kSlotsPerInterruptCheck) == 0) {
      thread->CheckForSafepoint();
    }
  }
  return result.ptr();
}

ArrayPtr Array::Slice(intptr_t start,
                      intptr_t count,
                      bool with_type_argument) const {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const Array& dest = Array::Handle(zone, Array::NewUninitialized(count));
  if (with_type_argument) {
    dest.SetTypeArguments(TypeArguments::Handle(zone, GetTypeArguments()));
  } else {
    dest.SetTypeArguments(Object::null_type_arguments());
  }
  if (!UseCardMarkingForAllocation(count)) {
    NoSafepointScope no_safepoint(thread);
    for (int i = 0; i < count; i++) {
      dest.untag()->set_element(i, untag()->element(i + start), thread);
    }
  } else {
    for (int i = 0; i < count; i++) {
      dest.untag()->set_element(i, untag()->element(i + start), thread);
      if (((i + 1) % kSlotsPerInterruptCheck) == 0) {
        thread->CheckForSafepoint();
      }
    }
  }
  return dest.ptr();
}

void Array::MakeImmutable() const {
  if (IsImmutable()) return;
  ASSERT(!IsCanonical());
  untag()->SetClassId(kImmutableArrayCid);
}

const char* Array::ToCString() const {
  if (IsNull()) {
    return IsImmutable() ? "_ImmutableList nullptr" : "_List nullptr";
  }
  Zone* zone = Thread::Current()->zone();
  const char* format =
      IsImmutable() ? "_ImmutableList len:%" Pd : "_List len:%" Pd;
  return zone->PrintToString(format, Length());
}

ArrayPtr Array::Grow(const Array& source,
                     intptr_t new_length,
                     Heap::Space space) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const Array& result =
      Array::Handle(zone, Array::NewUninitialized(new_length, space));
  intptr_t old_length = 0;
  if (!source.IsNull()) {
    old_length = source.Length();
    result.SetTypeArguments(
        TypeArguments::Handle(zone, source.GetTypeArguments()));
  } else {
    result.SetTypeArguments(Object::null_type_arguments());
  }
  ASSERT(new_length > old_length);  // Unnecessary copying of array.
  if (!UseCardMarkingForAllocation(new_length)) {
    NoSafepointScope no_safepoint(thread);
    for (intptr_t i = 0; i < old_length; i++) {
      result.untag()->set_element(i, source.untag()->element(i), thread);
    }
    for (intptr_t i = old_length; i < new_length; i++) {
      ASSERT(result.untag()->element(i) == Object::null());
    }
  } else {
    for (intptr_t i = 0; i < old_length; i++) {
      result.untag()->set_element(i, source.untag()->element(i), thread);
      if (((i + 1) % kSlotsPerInterruptCheck) == 0) {
        thread->CheckForSafepoint();
      }
    }
    for (intptr_t i = old_length; i < new_length; i++) {
      result.untag()->set_element(i, Object::null(), thread);
      if (((i + 1) % kSlotsPerInterruptCheck) == 0) {
        thread->CheckForSafepoint();
      }
    }
  }
  return result.ptr();
}

void Array::Truncate(intptr_t new_len) const {
  if (IsNull()) {
    return;
  }
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const Array& array = Array::Handle(zone, this->ptr());

  intptr_t old_len = array.Length();
  ASSERT(new_len <= old_len);
  if (old_len == new_len) {
    return;
  }
  intptr_t old_size = Array::InstanceSize(old_len);
  intptr_t new_size = Array::InstanceSize(new_len);

  NoSafepointScope no_safepoint;

  // If there is any left over space fill it with either an Array object or
  // just a plain object (depending on the amount of left over space) so
  // that it can be traversed over successfully during garbage collection.
  Object::MakeUnusedSpaceTraversable(array, old_size, new_size);

  // Update the size in the header field and length of the array object.
  // These release operations are balanced by acquire operations in the
  // concurrent sweeper.
  uword old_tags = array.untag()->tags_;
  uword new_tags;
  ASSERT(kArrayCid == UntaggedObject::ClassIdTag::decode(old_tags));
  do {
    new_tags = UntaggedObject::SizeTag::update(new_size, old_tags);
  } while (!array.untag()->tags_.compare_exchange_weak(
      old_tags, new_tags, std::memory_order_release));

  // Between the CAS of the header above and the SetLength below, the array is
  // temporarily in an inconsistent state. The header is considered the
  // overriding source of object size by UntaggedObject::HeapSize, but the
  // ASSERTs in UntaggedObject::HeapSizeFromClass must handle this special case.
  array.SetLengthRelease(new_len);
}

ArrayPtr Array::MakeFixedLength(const GrowableObjectArray& growable_array,
                                bool unique) {
  ASSERT(!growable_array.IsNull());
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  intptr_t used_len = growable_array.Length();
  // Get the type arguments and prepare to copy them.
  const TypeArguments& type_arguments =
      TypeArguments::Handle(growable_array.GetTypeArguments());
  if (used_len == 0) {
    if (type_arguments.IsNull() && !unique) {
      // This is a raw List (as in no type arguments), so we can return the
      // simple empty array.
      return Object::empty_array().ptr();
    }

    // The backing array may be a shared instance, or may not have correct
    // type parameters. Create a new empty array.
    Heap::Space space = thread->HasDartMutatorStack() ? Heap::kNew : Heap::kOld;
    Array& array = Array::Handle(zone, Array::New(0, space));
    array.SetTypeArguments(type_arguments);
    return array.ptr();
  }
  const Array& array = Array::Handle(zone, growable_array.data());
  ASSERT(array.IsArray());
  array.SetTypeArguments(type_arguments);

  // Null the GrowableObjectArray, we are removing its backing array.
  growable_array.SetLength(0);
  growable_array.SetData(Object::empty_array());

  // Truncate the old backing array and return it.
  array.Truncate(used_len);
  return array.ptr();
}

void Array::CanonicalizeFieldsLocked(Thread* thread) const {
  ASSERT(IsImmutable());
  intptr_t len = Length();
  if (len > 0) {
    Zone* zone = thread->zone();
    Instance& obj = Instance::Handle(zone);
    for (intptr_t i = 0; i < len; i++) {
      obj ^= At(i);
      obj = obj.CanonicalizeLocked(thread);
      this->SetAt(i, obj);
    }
  }
}

ImmutableArrayPtr ImmutableArray::New(intptr_t len, Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->immutable_array_class() !=
         Class::null());
  return static_cast<ImmutableArrayPtr>(Array::New(kClassId, len, space));
}

void GrowableObjectArray::Add(const Object& value, Heap::Space space) const {
  ASSERT(!IsNull());
  if (Length() == Capacity()) {
    // Grow from 0 to 3, and then double + 1.
    intptr_t new_capacity = (Capacity() * 2) | 3;
    if (new_capacity <= Capacity()) {
      Exceptions::ThrowOOM();
      UNREACHABLE();
    }
    Grow(new_capacity, space);
  }
  ASSERT(Length() < Capacity());
  intptr_t index = Length();
  SetLength(index + 1);
  SetAt(index, value);
}

void GrowableObjectArray::Grow(intptr_t new_capacity, Heap::Space space) const {
  ASSERT(new_capacity > Capacity());
  const Array& contents = Array::Handle(data());
  const Array& new_contents =
      Array::Handle(Array::Grow(contents, new_capacity, space));
  untag()->set_data(new_contents.ptr());
}

ObjectPtr GrowableObjectArray::RemoveLast() const {
  ASSERT(!IsNull());
  ASSERT(Length() > 0);
  intptr_t index = Length() - 1;
  const Array& contents = Array::Handle(data());
  const PassiveObject& obj = PassiveObject::Handle(contents.At(index));
  contents.SetAt(index, Object::null_object());
  SetLength(index);
  return obj.ptr();
}

GrowableObjectArrayPtr GrowableObjectArray::New(intptr_t capacity,
                                                Heap::Space space) {
  ArrayPtr raw_data = (capacity == 0) ? Object::empty_array().ptr()
                                      : Array::New(capacity, space);
  const Array& data = Array::Handle(raw_data);
  return New(data, space);
}

GrowableObjectArrayPtr GrowableObjectArray::New(const Array& array,
                                                Heap::Space space) {
  ASSERT(
      IsolateGroup::Current()->object_store()->growable_object_array_class() !=
      Class::null());
  const auto& result =
      GrowableObjectArray::Handle(Object::Allocate<GrowableObjectArray>(space));
  result.SetLength(0);
  result.SetData(array);
  return result.ptr();
}

const char* GrowableObjectArray::ToCString() const {
  if (IsNull()) {
    return "_GrowableList: null";
  }
  return OS::SCreate(Thread::Current()->zone(),
                     "Instance(length:%" Pd ") of '_GrowableList'", Length());
}

// Equivalent to Dart's operator "==" and hashCode.
class DefaultHashTraits {
 public:
  static const char* Name() { return "DefaultHashTraits"; }
  static bool ReportStats() { return false; }

  static bool IsMatch(const Object& a, const Object& b) {
    if (a.IsNull() || b.IsNull()) {
      return (a.IsNull() && b.IsNull());
    } else {
      return Instance::Cast(a).OperatorEquals(Instance::Cast(b));
    }
  }
  static uword Hash(const Object& obj) {
    if (obj.IsNull()) {
      return 0;
    }
    Thread* thread = Thread::Current();
    REUSABLE_INSTANCE_HANDLESCOPE(thread);
    Instance& hash_code = thread->InstanceHandle();
    hash_code ^= Instance::Cast(obj).HashCode();
    if (hash_code.IsInteger()) {
      return static_cast<uword>(Integer::Cast(hash_code).Value() & 0xFFFFFFFF);
    } else {
      return 0;
    }
  }
};

MapPtr Map::NewDefault(intptr_t class_id, Heap::Space space) {
  const Array& data = Array::Handle(Array::New(kInitialIndexSize, space));
  const TypedData& index = TypedData::Handle(
      TypedData::New(kTypedDataUint32ArrayCid, kInitialIndexSize, space));
  // On 32-bit, the top bits are wasted to avoid Mint allocation.
  const intptr_t kAvailableBits = (kSmiBits >= 32) ? 32 : kSmiBits;
  const intptr_t kInitialHashMask =
      (1 << (kAvailableBits - kInitialIndexBits)) - 1;
  return Map::New(class_id, data, index, kInitialHashMask, 0, 0, space);
}

MapPtr Map::New(intptr_t class_id,
                const Array& data,
                const TypedData& index,
                intptr_t hash_mask,
                intptr_t used_data,
                intptr_t deleted_keys,
                Heap::Space space) {
  ASSERT(class_id == kMapCid || class_id == kConstMapCid);
  ASSERT(IsolateGroup::Current()->object_store()->map_impl_class() !=
         Class::null());
  Map& result = Map::Handle(Map::NewUninitialized(class_id, space));
  result.set_data(data);
  result.set_index(index);
  result.set_hash_mask(hash_mask);
  result.set_used_data(used_data);
  result.set_deleted_keys(deleted_keys);
  return result.ptr();
}

MapPtr Map::NewUninitialized(intptr_t class_id, Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->map_impl_class() !=
         Class::null());
  return Object::AllocateVariant<Map>(class_id, space);
}

const char* Map::ToCString() const {
  Zone* zone = Thread::Current()->zone();
  return zone->PrintToString(
      "%s len:%" Pd, GetClassId() == kConstMapCid ? "_ConstMap" : "_Map",
      Length());
}

void LinkedHashBase::ComputeAndSetHashMask() const {
  ASSERT(IsImmutable());
  ASSERT_EQUAL(Smi::Value(deleted_keys()), 0);
  Thread* const thread = Thread::Current();
  Zone* const zone = thread->zone();

  const auto& data_array = Array::Handle(zone, data());
  const intptr_t data_length = Utils::RoundUpToPowerOfTwo(data_array.Length());
  const intptr_t index_size_mult = IsMap() ? 1 : 2;
  const intptr_t index_size = Utils::Maximum(LinkedHashBase::kInitialIndexSize,
                                             data_length * index_size_mult);
  ASSERT(Utils::IsPowerOfTwo(index_size));

  const intptr_t hash_mask = IndexSizeToHashMask(index_size);
  set_hash_mask(hash_mask);
}

bool LinkedHashBase::CanonicalizeEquals(const Instance& other) const {
  ASSERT(IsImmutable());

  if (this->ptr() == other.ptr()) {
    // Both handles point to the same raw instance.
    return true;
  }
  if (other.IsNull()) {
    return false;
  }
  if (GetClassId() != other.GetClassId()) {
    return false;
  }

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

  const LinkedHashBase& other_map = LinkedHashBase::Cast(other);

  if (!Smi::Handle(zone, used_data())
           .Equals(Smi::Handle(zone, other_map.used_data()))) {
    return false;
  }

  // Immutable maps and sets do not have deleted keys.
  ASSERT_EQUAL(RawSmiValue(deleted_keys()), 0);

  if (!Array::Handle(zone, data())
           .CanonicalizeEquals(Array::Handle(zone, other_map.data()))) {
    return false;
  }

  if (GetTypeArguments() == other.GetTypeArguments()) {
    return true;
  }
  const TypeArguments& type_args =
      TypeArguments::Handle(zone, GetTypeArguments());
  const TypeArguments& other_type_args =
      TypeArguments::Handle(zone, other.GetTypeArguments());
  return type_args.Equals(other_type_args);
}

uint32_t LinkedHashBase::CanonicalizeHash() const {
  ASSERT(IsImmutable());

  Thread* thread = Thread::Current();
  uint32_t hash = thread->heap()->GetCanonicalHash(ptr());
  if (hash != 0) {
    return hash;
  }

  // Immutable maps and sets do not have deleted keys.
  ASSERT_EQUAL(RawSmiValue(deleted_keys()), 0);

  Zone* zone = thread->zone();
  auto& member = Instance::Handle(zone, GetTypeArguments());
  hash = member.CanonicalizeHash();
  member = data();
  hash = CombineHashes(hash, member.CanonicalizeHash());
  member = used_data();
  hash = CombineHashes(hash, member.CanonicalizeHash());
  hash = FinalizeHash(hash, kHashBits);
  thread->heap()->SetCanonicalHash(ptr(), hash);
  return hash;
}

void LinkedHashBase::CanonicalizeFieldsLocked(Thread* thread) const {
  ASSERT(IsImmutable());

  Zone* zone = thread->zone();

  TypeArguments& type_args = TypeArguments::Handle(zone, GetTypeArguments());
  if (!type_args.IsNull()) {
    type_args = type_args.Canonicalize(thread);
    SetTypeArguments(type_args);
  }

  auto& data_array = Array::Handle(zone, data());
  data_array.MakeImmutable();
  data_array ^= data_array.CanonicalizeLocked(thread);
  set_data(data_array);

  // Ignoring index. It will be initially null, created on first use, and
  // possibly non-null here if we are rehashing.
}

ConstMapPtr ConstMap::NewDefault(Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->const_map_impl_class() !=
         Class::null());
  return static_cast<ConstMapPtr>(Map::NewDefault(kClassId, space));
}

ConstMapPtr ConstMap::NewUninitialized(Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->const_map_impl_class() !=
         Class::null());
  return static_cast<ConstMapPtr>(Map::NewUninitialized(kClassId, space));
}

SetPtr Set::New(intptr_t class_id,
                const Array& data,
                const TypedData& index,
                intptr_t hash_mask,
                intptr_t used_data,
                intptr_t deleted_keys,
                Heap::Space space) {
  ASSERT(class_id == kSetCid || class_id == kConstSetCid);
  ASSERT(IsolateGroup::Current()->object_store()->set_impl_class() !=
         Class::null());
  Set& result = Set::Handle(Set::NewUninitialized(class_id, space));
  result.set_data(data);
  result.set_index(index);
  result.set_hash_mask(hash_mask);
  result.set_used_data(used_data);
  result.set_deleted_keys(deleted_keys);
  return result.ptr();
}

SetPtr Set::NewDefault(intptr_t class_id, Heap::Space space) {
  const Array& data = Array::Handle(Array::New(kInitialIndexSize, space));
  const TypedData& index = TypedData::Handle(
      TypedData::New(kTypedDataUint32ArrayCid, kInitialIndexSize, space));
  // On 32-bit, the top bits are wasted to avoid Mint allocation.
  const intptr_t kAvailableBits = (kSmiBits >= 32) ? 32 : kSmiBits;
  const intptr_t kInitialHashMask =
      (1 << (kAvailableBits - kInitialIndexBits)) - 1;
  return Set::New(class_id, data, index, kInitialHashMask, 0, 0, space);
}

SetPtr Set::NewUninitialized(intptr_t class_id, Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->set_impl_class() !=
         Class::null());
  return Object::AllocateVariant<Set>(class_id, space);
}

ConstSetPtr ConstSet::NewDefault(Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->const_set_impl_class() !=
         Class::null());
  return static_cast<ConstSetPtr>(Set::NewDefault(kClassId, space));
}

ConstSetPtr ConstSet::NewUninitialized(Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->const_set_impl_class() !=
         Class::null());
  return static_cast<ConstSetPtr>(Set::NewUninitialized(kClassId, space));
}

const char* Set::ToCString() const {
  Zone* zone = Thread::Current()->zone();
  return zone->PrintToString(
      "%s len:%" Pd, GetClassId() == kConstSetCid ? "_ConstSet" : "_Set",
      Length());
}

const char* FutureOr::ToCString() const {
  // FutureOr is an abstract class.
  UNREACHABLE();
}

Float32x4Ptr Float32x4::New(float v0,
                            float v1,
                            float v2,
                            float v3,
                            Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->float32x4_class() !=
         Class::null());
  const auto& result = Float32x4::Handle(Object::Allocate<Float32x4>(space));
  result.set_x(v0);
  result.set_y(v1);
  result.set_z(v2);
  result.set_w(v3);
  return result.ptr();
}

Float32x4Ptr Float32x4::New(simd128_value_t value, Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->float32x4_class() !=
         Class::null());
  const auto& result = Float32x4::Handle(Object::Allocate<Float32x4>(space));
  result.set_value(value);
  return result.ptr();
}

simd128_value_t Float32x4::value() const {
  return LoadUnaligned(
      reinterpret_cast<const simd128_value_t*>(&untag()->value_));
}

void Float32x4::set_value(simd128_value_t value) const {
  StoreUnaligned(reinterpret_cast<simd128_value_t*>(&ptr()->untag()->value_),
                 value);
}

void Float32x4::set_x(float value) const {
  StoreNonPointer(&untag()->value_[0], value);
}

void Float32x4::set_y(float value) const {
  StoreNonPointer(&untag()->value_[1], value);
}

void Float32x4::set_z(float value) const {
  StoreNonPointer(&untag()->value_[2], value);
}

void Float32x4::set_w(float value) const {
  StoreNonPointer(&untag()->value_[3], value);
}

float Float32x4::x() const {
  return untag()->value_[0];
}

float Float32x4::y() const {
  return untag()->value_[1];
}

float Float32x4::z() const {
  return untag()->value_[2];
}

float Float32x4::w() const {
  return untag()->value_[3];
}

bool Float32x4::CanonicalizeEquals(const Instance& other) const {
  return memcmp(&untag()->value_, Float32x4::Cast(other).untag()->value_,
                sizeof(simd128_value_t)) == 0;
}

uint32_t Float32x4::CanonicalizeHash() const {
  return HashBytes(reinterpret_cast<const uint8_t*>(&untag()->value_),
                   sizeof(simd128_value_t));
}

const char* Float32x4::ToCString() const {
  float _x = x();
  float _y = y();
  float _z = z();
  float _w = w();
  return OS::SCreate(Thread::Current()->zone(), "[%f, %f, %f, %f]", _x, _y, _z,
                     _w);
}

Int32x4Ptr Int32x4::New(int32_t v0,
                        int32_t v1,
                        int32_t v2,
                        int32_t v3,
                        Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->int32x4_class() !=
         Class::null());
  const auto& result = Int32x4::Handle(Object::Allocate<Int32x4>(space));
  result.set_x(v0);
  result.set_y(v1);
  result.set_z(v2);
  result.set_w(v3);
  return result.ptr();
}

Int32x4Ptr Int32x4::New(simd128_value_t value, Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->int32x4_class() !=
         Class::null());
  const auto& result = Int32x4::Handle(Object::Allocate<Int32x4>(space));
  result.set_value(value);
  return result.ptr();
}

void Int32x4::set_x(int32_t value) const {
  StoreNonPointer(&untag()->value_[0], value);
}

void Int32x4::set_y(int32_t value) const {
  StoreNonPointer(&untag()->value_[1], value);
}

void Int32x4::set_z(int32_t value) const {
  StoreNonPointer(&untag()->value_[2], value);
}

void Int32x4::set_w(int32_t value) const {
  StoreNonPointer(&untag()->value_[3], value);
}

int32_t Int32x4::x() const {
  return untag()->value_[0];
}

int32_t Int32x4::y() const {
  return untag()->value_[1];
}

int32_t Int32x4::z() const {
  return untag()->value_[2];
}

int32_t Int32x4::w() const {
  return untag()->value_[3];
}

simd128_value_t Int32x4::value() const {
  return LoadUnaligned(
      reinterpret_cast<const simd128_value_t*>(&untag()->value_));
}

void Int32x4::set_value(simd128_value_t value) const {
  StoreUnaligned(reinterpret_cast<simd128_value_t*>(&ptr()->untag()->value_),
                 value);
}

bool Int32x4::CanonicalizeEquals(const Instance& other) const {
  return memcmp(&untag()->value_, Int32x4::Cast(other).untag()->value_,
                sizeof(simd128_value_t)) == 0;
}

uint32_t Int32x4::CanonicalizeHash() const {
  return HashBytes(reinterpret_cast<const uint8_t*>(&untag()->value_),
                   sizeof(simd128_value_t));
}

const char* Int32x4::ToCString() const {
  int32_t _x = x();
  int32_t _y = y();
  int32_t _z = z();
  int32_t _w = w();
  return OS::SCreate(Thread::Current()->zone(), "[%08x, %08x, %08x, %08x]", _x,
                     _y, _z, _w);
}

Float64x2Ptr Float64x2::New(double value0, double value1, Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->float64x2_class() !=
         Class::null());
  const auto& result = Float64x2::Handle(Object::Allocate<Float64x2>(space));
  result.set_x(value0);
  result.set_y(value1);
  return result.ptr();
}

Float64x2Ptr Float64x2::New(simd128_value_t value, Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->float64x2_class() !=
         Class::null());
  const auto& result = Float64x2::Handle(Object::Allocate<Float64x2>(space));
  result.set_value(value);
  return result.ptr();
}

double Float64x2::x() const {
  return untag()->value_[0];
}

double Float64x2::y() const {
  return untag()->value_[1];
}

void Float64x2::set_x(double x) const {
  StoreNonPointer(&untag()->value_[0], x);
}

void Float64x2::set_y(double y) const {
  StoreNonPointer(&untag()->value_[1], y);
}

simd128_value_t Float64x2::value() const {
  return simd128_value_t().readFrom(&untag()->value_[0]);
}

void Float64x2::set_value(simd128_value_t value) const {
  StoreSimd128(&untag()->value_[0], value);
}

bool Float64x2::CanonicalizeEquals(const Instance& other) const {
  return memcmp(&untag()->value_, Float64x2::Cast(other).untag()->value_,
                sizeof(simd128_value_t)) == 0;
}

uint32_t Float64x2::CanonicalizeHash() const {
  return HashBytes(reinterpret_cast<const uint8_t*>(&untag()->value_),
                   sizeof(simd128_value_t));
}

const char* Float64x2::ToCString() const {
  double _x = x();
  double _y = y();
  return OS::SCreate(Thread::Current()->zone(), "[%f, %f]", _x, _y);
}

const intptr_t
    TypedDataBase::element_size_table[TypedDataBase::kNumElementSizes] = {
        1,   // kTypedDataInt8ArrayCid.
        1,   // kTypedDataUint8ArrayCid.
        1,   // kTypedDataUint8ClampedArrayCid.
        2,   // kTypedDataInt16ArrayCid.
        2,   // kTypedDataUint16ArrayCid.
        4,   // kTypedDataInt32ArrayCid.
        4,   // kTypedDataUint32ArrayCid.
        8,   // kTypedDataInt64ArrayCid.
        8,   // kTypedDataUint64ArrayCid.
        4,   // kTypedDataFloat32ArrayCid.
        8,   // kTypedDataFloat64ArrayCid.
        16,  // kTypedDataFloat32x4ArrayCid.
        16,  // kTypedDataInt32x4ArrayCid.
        16,  // kTypedDataFloat64x2ArrayCid,
};

bool TypedData::CanonicalizeEquals(const Instance& other) const {
  if (this->ptr() == other.ptr()) {
    // Both handles point to the same raw instance.
    return true;
  }

  if (!other.IsTypedData() || other.IsNull()) {
    return false;
  }

  const TypedData& other_typed_data = TypedData::Cast(other);

  if (this->ElementType() != other_typed_data.ElementType()) {
    return false;
  }

  const intptr_t len = this->LengthInBytes();
  if (len != other_typed_data.LengthInBytes()) {
    return false;
  }
  NoSafepointScope no_safepoint;
  return (len == 0) ||
         (memcmp(DataAddr(0), other_typed_data.DataAddr(0), len) == 0);
}

uint32_t TypedData::CanonicalizeHash() const {
  const intptr_t len = this->LengthInBytes();
  if (len == 0) {
    return 1;
  }
  uint32_t hash = len;
  for (intptr_t i = 0; i < len; i++) {
    hash = CombineHashes(len, GetUint8(i));
  }
  return FinalizeHash(hash, kHashBits);
}

TypedDataPtr TypedData::New(intptr_t class_id,
                            intptr_t len,
                            Heap::Space space) {
  if (len < 0 || len > TypedData::MaxElements(class_id)) {
    FATAL("Fatal error in TypedData::New: invalid len %" Pd "\n", len);
  }
  auto raw = Object::AllocateVariant<TypedData>(
      class_id, space, len * ElementSizeInBytes(class_id));
  NoSafepointScope no_safepoint;
  raw->untag()->set_length(Smi::New(len));
  raw->untag()->RecomputeDataField();
  return raw;
}

TypedDataPtr TypedData::Grow(const TypedData& current,
                             intptr_t len,
                             Heap::Space space) {
  ASSERT(len > current.Length());
  const auto& new_td =
      TypedData::Handle(TypedData::New(current.GetClassId(), len, space));
  {
    NoSafepointScope no_safepoint_scope;
    memcpy(new_td.DataAddr(0), current.DataAddr(0), current.LengthInBytes());
  }
  return new_td.ptr();
}

const char* TypedData::ToCString() const {
  const Class& cls = Class::Handle(clazz());
  return cls.ScrubbedNameCString();
}

FinalizablePersistentHandle* ExternalTypedData::AddFinalizer(
    void* peer,
    Dart_HandleFinalizer callback,
    intptr_t external_size) const {
  return dart::AddFinalizer(*this, peer, callback, external_size);
}

ExternalTypedDataPtr ExternalTypedData::New(
    intptr_t class_id,
    uint8_t* data,
    intptr_t len,
    Heap::Space space,
    bool perform_eager_msan_initialization_check) {
  if (len < 0 || len > ExternalTypedData::MaxElements(class_id)) {
    FATAL("Fatal error in ExternalTypedData::New: invalid len %" Pd "\n", len);
  }

  if (perform_eager_msan_initialization_check) {
    // Once the TypedData is created, Dart might read this memory. Check for
    // initialization at construction to make it easier to track the source.
    MSAN_CHECK_INITIALIZED(data, len);
  }

  const auto& result = ExternalTypedData::Handle(
      Object::AllocateVariant<ExternalTypedData>(class_id, space));
  result.SetLength(len);
  result.SetData(data);
  return result.ptr();
}

ExternalTypedDataPtr ExternalTypedData::NewFinalizeWithFree(uint8_t* data,
                                                            intptr_t len) {
  ExternalTypedData& result = ExternalTypedData::Handle(ExternalTypedData::New(
      kExternalTypedDataUint8ArrayCid, data, len, Heap::kOld));
  result.AddFinalizer(
      data, [](void* isolate_callback_data, void* data) { free(data); }, len);
  return result.ptr();
}

TypedDataViewPtr TypedDataView::New(intptr_t class_id, Heap::Space space) {
  return Object::AllocateVariant<TypedDataView>(class_id, space);
}

TypedDataViewPtr TypedDataView::New(intptr_t class_id,
                                    const TypedDataBase& typed_data,
                                    intptr_t offset_in_bytes,
                                    intptr_t length,
                                    Heap::Space space) {
  auto& result = TypedDataView::Handle(TypedDataView::New(class_id, space));
  result.InitializeWith(typed_data, offset_in_bytes, length);
  return result.ptr();
}

bool TypedDataBase::IsExternalOrExternalView() const {
  if (IsExternalTypedData()) return true;
  if (IsTypedDataView()) {
    const auto& backing =
        TypedDataBase::Handle(TypedDataView::Cast(*this).typed_data());
    return backing.IsExternalTypedData();
  }
  return false;
}

TypedDataViewPtr TypedDataBase::ViewFromTo(intptr_t start,
                                           intptr_t end,
                                           Heap::Space space) const {
  const intptr_t len = end - start;
  ASSERT(0 <= len);
  ASSERT(start < Length());
  ASSERT((start + len) <= Length());

  const intptr_t cid = GetClassId();

  if (IsTypedDataView()) {
    const auto& view = TypedDataView::Cast(*this);
    const auto& td = TypedDataBase::Handle(view.typed_data());
    const intptr_t view_offset = Smi::Value(view.offset_in_bytes());
    ASSERT(IsTypedDataViewClassId(cid));
    return TypedDataView::New(cid, ExternalTypedData::Cast(td),
                              view_offset + start, len, Heap::kOld);
  } else if (IsExternalTypedData()) {
    ASSERT(IsExternalTypedDataClassId(cid));
    ASSERT(IsTypedDataViewClassId(cid - 1));
    return TypedDataView::New(cid - 1, *this, start, len, Heap::kOld);
  }
  RELEASE_ASSERT(IsTypedData());
  ASSERT(IsExternalTypedDataClassId(cid));
  ASSERT(IsTypedDataViewClassId(cid + 1));
  return TypedDataView::New(cid + 1, *this, start, len, Heap::kOld);
}

const char* TypedDataBase::ToCString() const {
  // There are no instances of UntaggedTypedDataBase.
  UNREACHABLE();
  return nullptr;
}

const char* TypedDataView::ToCString() const {
  const Class& cls = Class::Handle(clazz());
  return cls.ScrubbedNameCString();
}

const char* ExternalTypedData::ToCString() const {
  const Class& cls = Class::Handle(clazz());
  return cls.ScrubbedNameCString();
}

PointerPtr Pointer::New(uword native_address, Heap::Space space) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  const auto& type_args = TypeArguments::Handle(
      zone, IsolateGroup::Current()->object_store()->type_argument_never());

  const Class& cls =
      Class::Handle(IsolateGroup::Current()->class_table()->At(kPointerCid));
  cls.EnsureIsAllocateFinalized(Thread::Current());

  const auto& result = Pointer::Handle(zone, Object::Allocate<Pointer>(space));
  result.SetTypeArguments(type_args);
  result.SetNativeAddress(native_address);

  return result.ptr();
}

const char* Pointer::ToCString() const {
  return OS::SCreate(Thread::Current()->zone(), "Pointer: address=0x%" Px,
                     NativeAddress());
}

DynamicLibraryPtr DynamicLibrary::New(void* handle,
                                      bool canBeClosed,
                                      Heap::Space space) {
  const auto& result =
      DynamicLibrary::Handle(Object::Allocate<DynamicLibrary>(space));
  ASSERT_EQUAL(result.IsClosed(), false);
  result.SetHandle(handle);
  result.SetCanBeClosed(canBeClosed);
  return result.ptr();
}

bool Pointer::IsPointer(const Instance& obj) {
  return IsFfiPointerClassId(obj.ptr()->GetClassId());
}

bool Instance::IsPointer() const {
  return Pointer::IsPointer(*this);
}

const char* DynamicLibrary::ToCString() const {
  return OS::SCreate(Thread::Current()->zone(), "DynamicLibrary: handle=0x%" Px,
                     reinterpret_cast<uintptr_t>(GetHandle()));
}

CapabilityPtr Capability::New(uint64_t id, Heap::Space space) {
  const auto& result = Capability::Handle(Object::Allocate<Capability>(space));
  result.StoreNonPointer(&result.untag()->id_, id);
  return result.ptr();
}

const char* Capability::ToCString() const {
  return "Capability";
}

ReceivePortPtr ReceivePort::New(Dart_Port id,
                                const String& debug_name,
                                Heap::Space space) {
  ASSERT(id != ILLEGAL_PORT);
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const SendPort& send_port =
      SendPort::Handle(zone, SendPort::New(id, thread->isolate_group()->id()));
#if !defined(PRODUCT)
  const StackTrace& allocation_location_ =
      HasStack() ? GetCurrentStackTrace(0) : StackTrace::Handle();
#endif  // !defined(PRODUCT)

  const auto& result =
      ReceivePort::Handle(zone, Object::Allocate<ReceivePort>(space));
  result.untag()->set_send_port(send_port.ptr());
  result.untag()->set_bitfield(
      Smi::New(IsOpen::encode(true) | IsKeepIsolateAlive::encode(true)));
#if !defined(PRODUCT)
  result.untag()->set_debug_name(debug_name.ptr());
  result.untag()->set_allocation_location(allocation_location_.ptr());
#endif  // !defined(PRODUCT)
  return result.ptr();
}

const char* ReceivePort::ToCString() const {
  return "ReceivePort";
}

SendPortPtr SendPort::New(Dart_Port id, Heap::Space space) {
  return New(id, ILLEGAL_PORT, space);
}

SendPortPtr SendPort::New(Dart_Port id,
                          Dart_Port origin_id,
                          Heap::Space space) {
  ASSERT(id != ILLEGAL_PORT);
  const auto& result = SendPort::Handle(Object::Allocate<SendPort>(space));
  result.StoreNonPointer(&result.untag()->id_, id);
  result.StoreNonPointer(&result.untag()->origin_id_, origin_id);
  return result.ptr();
}

const char* SendPort::ToCString() const {
  return "SendPort";
}

static void TransferableTypedDataFinalizer(void* isolate_callback_data,
                                           void* peer) {
  delete (reinterpret_cast<TransferableTypedDataPeer*>(peer));
}

TransferableTypedDataPtr TransferableTypedData::New(uint8_t* data,
                                                    intptr_t length) {
  auto* const peer = new TransferableTypedDataPeer(data, length);

  Thread* thread = Thread::Current();
  const auto& result =
      TransferableTypedData::Handle(Object::Allocate<TransferableTypedData>(
          thread->heap()->SpaceForExternal(length)));
  thread->heap()->SetPeer(result.ptr(), peer);

  // Set up finalizer so it frees allocated memory if handle is
  // garbage-collected.
  FinalizablePersistentHandle* finalizable_ref =
      FinalizablePersistentHandle::New(thread->isolate_group(), result, peer,
                                       &TransferableTypedDataFinalizer, length,
                                       /*auto_delete=*/true);
  ASSERT(finalizable_ref != nullptr);
  peer->set_handle(finalizable_ref);

  return result.ptr();
}

const char* TransferableTypedData::ToCString() const {
  return "TransferableTypedData";
}

bool Closure::CanonicalizeEquals(const Instance& other) const {
  if (!other.IsClosure()) return false;

  const Closure& other_closure = Closure::Cast(other);
  return (instantiator_type_arguments() ==
          other_closure.instantiator_type_arguments()) &&
         (function_type_arguments() ==
          other_closure.function_type_arguments()) &&
         (delayed_type_arguments() == other_closure.delayed_type_arguments()) &&
         (function() == other_closure.function()) &&
         (RawContext() == other_closure.RawContext());
}

void Closure::CanonicalizeFieldsLocked(Thread* thread) const {
  TypeArguments& type_args = TypeArguments::Handle();
  type_args = instantiator_type_arguments();
  if (!type_args.IsNull()) {
    type_args = type_args.Canonicalize(thread);
    set_instantiator_type_arguments(type_args);
  }
  type_args = function_type_arguments();
  if (!type_args.IsNull()) {
    type_args = type_args.Canonicalize(thread);
    set_function_type_arguments(type_args);
  }
  type_args = delayed_type_arguments();
  if (!type_args.IsNull()) {
    type_args = type_args.Canonicalize(thread);
    set_delayed_type_arguments(type_args);
  }
  // Ignore function, context, hash.
}

const char* Closure::ToCString() const {
  auto const thread = Thread::Current();
  auto const zone = thread->zone();
  ZoneTextBuffer buffer(zone);
  buffer.AddString("Closure: ");
  const Function& fun = Function::Handle(zone, function());
  const FunctionType& sig =
      FunctionType::Handle(zone, GetInstantiatedSignature(zone));
  sig.Print(kUserVisibleName, &buffer);
  if (fun.IsImplicitClosureFunction()) {
    buffer.Printf(" from %s", fun.ToCString());
  }
  return buffer.buffer();
}

uword Closure::ComputeHash() const {
  Thread* thread = Thread::Current();
  DEBUG_ASSERT(thread->TopErrorHandlerIsExitFrame());
  Zone* zone = thread->zone();
  const Function& func = Function::Handle(zone, function());
  uint32_t result = 0;
  if (func.IsImplicitClosureFunction() || func.IsGeneric()) {
    // Combine function's hash code, delayed type arguments hash code
    // (if generic), and identityHashCode of cached receiver (if implicit
    // instance closure).
    result = static_cast<uint32_t>(func.Hash());
    if (func.IsGeneric()) {
      const TypeArguments& delayed_type_args =
          TypeArguments::Handle(zone, delayed_type_arguments());
      result = CombineHashes(result, delayed_type_args.Hash());
    }
    if (func.IsImplicitInstanceClosureFunction()) {
      const Instance& receiver =
          Instance::Handle(zone, GetImplicitClosureReceiver());
      const Integer& receiverHash =
          Integer::Handle(zone, receiver.IdentityHashCode(thread));
      result =
          CombineHashes(result, static_cast<uint32_t>(receiverHash.Value()));
    }
  } else {
    // Non-implicit closures of non-generic functions are unique,
    // so identityHashCode of closure object is good enough.
    const Integer& identityHash =
        Integer::Handle(zone, this->IdentityHashCode(thread));
    result = static_cast<uint32_t>(identityHash.Value());
  }
  return FinalizeHash(result, String::kHashBits);
}

ClosurePtr Closure::New(const TypeArguments& instantiator_type_arguments,
                        const TypeArguments& function_type_arguments,
                        const Function& function,
                        const Object& context,
                        Heap::Space space) {
  // We store null delayed type arguments, not empty ones, in closures with
  // non-generic functions a) to make method extraction slightly faster and
  // b) to make the Closure::IsGeneric check fast.
  // Keep in sync with StubCodeCompiler::GenerateAllocateClosureStub.
  return Closure::New(instantiator_type_arguments, function_type_arguments,
                      function.IsGeneric() ? Object::empty_type_arguments()
                                           : Object::null_type_arguments(),
                      function, context, space);
}

ClosurePtr Closure::New(const TypeArguments& instantiator_type_arguments,
                        const TypeArguments& function_type_arguments,
                        const TypeArguments& delayed_type_arguments,
                        const Function& function,
                        const Object& context,
                        Heap::Space space) {
  ASSERT(instantiator_type_arguments.IsCanonical());
  ASSERT(function_type_arguments.IsCanonical());
  ASSERT(delayed_type_arguments.IsCanonical());
  ASSERT(FunctionType::Handle(function.signature()).IsCanonical());
  ASSERT(
      (function.IsImplicitInstanceClosureFunction() && context.IsInstance()) ||
      (function.IsNonImplicitClosureFunction() && context.IsContext()) ||
      context.IsNull());
  const auto& result = Closure::Handle(Object::Allocate<Closure>(space));
  result.untag()->set_instantiator_type_arguments(
      instantiator_type_arguments.ptr());
  result.untag()->set_function_type_arguments(function_type_arguments.ptr());
  result.untag()->set_delayed_type_arguments(delayed_type_arguments.ptr());
  result.untag()->set_function(function.ptr());
  result.untag()->set_context(context.ptr());
#if defined(DART_PRECOMPILED_RUNTIME)
  result.set_entry_point(function.entry_point());
#endif
  return result.ptr();
}

FunctionTypePtr Closure::GetInstantiatedSignature(Zone* zone) const {
  const Function& fun = Function::Handle(zone, function());
  FunctionType& sig = FunctionType::Handle(zone, fun.signature());
  TypeArguments& fn_type_args =
      TypeArguments::Handle(zone, function_type_arguments());
  const TypeArguments& delayed_type_args =
      TypeArguments::Handle(zone, delayed_type_arguments());
  const TypeArguments& inst_type_args =
      TypeArguments::Handle(zone, instantiator_type_arguments());

  // We detect the case of a partial tearoff type application and substitute the
  // type arguments for the type parameters of the function.
  intptr_t num_free_params;
  if (!IsGeneric() && fun.IsGeneric()) {
    num_free_params = kCurrentAndEnclosingFree;
    fn_type_args = delayed_type_args.Prepend(
        zone, fn_type_args, sig.NumParentTypeArguments(),
        sig.NumTypeParameters() + sig.NumParentTypeArguments());
  } else {
    num_free_params = kAllFree;
  }
  if (num_free_params == kCurrentAndEnclosingFree || !sig.IsInstantiated()) {
    sig ^= sig.InstantiateFrom(inst_type_args, fn_type_args, num_free_params,
                               Heap::kOld);
  }
  return sig.ptr();
}

bool StackTrace::skip_sync_start_in_parent_stack() const {
  return untag()->skip_sync_start_in_parent_stack;
}

void StackTrace::set_skip_sync_start_in_parent_stack(bool value) const {
  StoreNonPointer(&untag()->skip_sync_start_in_parent_stack, value);
}

intptr_t StackTrace::Length() const {
  const Array& code_array = Array::Handle(untag()->code_array());
  return code_array.Length();
}

ObjectPtr StackTrace::CodeAtFrame(intptr_t frame_index) const {
  const Array& code_array = Array::Handle(untag()->code_array());
  return code_array.At(frame_index);
}

void StackTrace::SetCodeAtFrame(intptr_t frame_index,
                                const Object& code) const {
  const Array& code_array = Array::Handle(untag()->code_array());
  code_array.SetAt(frame_index, code);
}

uword StackTrace::PcOffsetAtFrame(intptr_t frame_index) const {
  const TypedData& pc_offset_array =
      TypedData::Handle(untag()->pc_offset_array());
  return pc_offset_array.GetUintPtr(frame_index * kWordSize);
}

void StackTrace::SetPcOffsetAtFrame(intptr_t frame_index,
                                    uword pc_offset) const {
  const TypedData& pc_offset_array =
      TypedData::Handle(untag()->pc_offset_array());
  pc_offset_array.SetUintPtr(frame_index * kWordSize, pc_offset);
}

void StackTrace::set_async_link(const StackTrace& async_link) const {
  untag()->set_async_link(async_link.ptr());
}

void StackTrace::set_code_array(const Array& code_array) const {
  untag()->set_code_array(code_array.ptr());
}

void StackTrace::set_pc_offset_array(const TypedData& pc_offset_array) const {
  untag()->set_pc_offset_array(pc_offset_array.ptr());
}

void StackTrace::set_expand_inlined(bool value) const {
  StoreNonPointer(&untag()->expand_inlined_, value);
}

bool StackTrace::expand_inlined() const {
  return untag()->expand_inlined_;
}

StackTracePtr StackTrace::New(const Array& code_array,
                              const TypedData& pc_offset_array,
                              Heap::Space space) {
  const auto& result = StackTrace::Handle(Object::Allocate<StackTrace>(space));
  result.set_code_array(code_array);
  result.set_pc_offset_array(pc_offset_array);
  result.set_expand_inlined(true);  // default.
  ASSERT_EQUAL(result.skip_sync_start_in_parent_stack(), false);
  return result.ptr();
}

StackTracePtr StackTrace::New(const Array& code_array,
                              const TypedData& pc_offset_array,
                              const StackTrace& async_link,
                              bool skip_sync_start_in_parent_stack,
                              Heap::Space space) {
  const auto& result = StackTrace::Handle(Object::Allocate<StackTrace>(space));
  result.set_async_link(async_link);
  result.set_code_array(code_array);
  result.set_pc_offset_array(pc_offset_array);
  result.set_expand_inlined(true);  // default.
  result.set_skip_sync_start_in_parent_stack(skip_sync_start_in_parent_stack);
  return result.ptr();
}

#if defined(DART_PRECOMPILED_RUNTIME)
static bool TryPrintNonSymbolicStackFrameBodyRelative(
    BaseTextBuffer* buffer,
    uword call_addr,
    uword instructions,
    bool vm,
    LoadingUnit* unit = nullptr) {
  const Image image(reinterpret_cast<const uint8_t*>(instructions));
  if (!image.contains(call_addr)) return false;
  if (unit != nullptr) {
    ASSERT(!unit->IsNull());
    // Add the unit ID to the stack frame, so the correct loading unit
    // information from the header can be checked.
    buffer->Printf(" unit %" Pd "", unit->id());
  }
  auto const offset = call_addr - instructions;
  // Only print the relocated address of the call when we know the saved
  // debugging information (if any) will have the same relocated address.
  // Also only print 'virt' fields for isolate addresses.
  if (!vm && image.compiled_to_shared_object()) {
    const uword relocated_section_start =
        image.instructions_relocated_address();
    buffer->Printf(" virt %" Pp "", relocated_section_start + offset);
  }
  const char* symbol = vm ? kVmSnapshotInstructionsAsmSymbol
                          : kIsolateSnapshotInstructionsAsmSymbol;
  buffer->Printf(" %s+0x%" Px "\n", symbol, offset);
  return true;
}

// Prints the best representation(s) for the call address.
static void PrintNonSymbolicStackFrameBody(BaseTextBuffer* buffer,
                                           uword call_addr,
                                           uword isolate_instructions,
                                           uword vm_instructions,
                                           const Array& loading_units,
                                           LoadingUnit* unit) {
  if (TryPrintNonSymbolicStackFrameBodyRelative(buffer, call_addr,
                                                vm_instructions,
                                                /*vm=*/true)) {
    return;
  }

  if (!loading_units.IsNull()) {
    // All non-VM stack frames should include the loading unit id.
    const intptr_t unit_count = loading_units.Length();
    for (intptr_t i = LoadingUnit::kRootId; i < unit_count; i++) {
      *unit ^= loading_units.At(i);
      if (!unit->has_instructions_image()) continue;
      auto const instructions =
          reinterpret_cast<uword>(unit->instructions_image());
      if (TryPrintNonSymbolicStackFrameBodyRelative(buffer, call_addr,
                                                    instructions,
                                                    /*vm=*/false, unit)) {
        return;
      }
    }
  } else {
    if (TryPrintNonSymbolicStackFrameBodyRelative(buffer, call_addr,
                                                  isolate_instructions,
                                                  /*vm=*/false)) {
      return;
    }
  }

  // The stack trace printer should never end up here, since these are not
  // addresses within a loading unit or the VM or app isolate instructions
  // sections. Thus, make it easy to notice when looking at the stack trace.
  buffer->Printf(" <invalid Dart instruction address>\n");
}
#endif

static void PrintSymbolicStackFrameIndex(BaseTextBuffer* buffer,
                                         intptr_t frame_index) {
  buffer->Printf("#%-6" Pd "", frame_index);
}

static void PrintSymbolicStackFrameBody(BaseTextBuffer* buffer,
                                        const char* function_name,
                                        const char* url,
                                        intptr_t line = -1,
                                        intptr_t column = -1) {
  buffer->Printf(" %s (%s", function_name, url);
  if (line >= 0) {
    buffer->Printf(":%" Pd "", line);
    if (column >= 0) {
      buffer->Printf(":%" Pd "", column);
    }
  }
  buffer->Printf(")\n");
}

static void PrintSymbolicStackFrame(Zone* zone,
                                    BaseTextBuffer* buffer,
                                    const Function& function,
                                    TokenPosition token_pos_or_line,
                                    intptr_t frame_index,
                                    bool is_line = false) {
  ASSERT(!function.IsNull());
  const auto& script = Script::Handle(zone, function.script());
  const char* function_name = function.QualifiedUserVisibleNameCString();
  const char* url = script.IsNull()
                        ? "Kernel"
                        : String::Handle(zone, script.url()).ToCString();

  // If the URI starts with "data:application/dart;" this is a URI encoded
  // script so we shouldn't print the entire URI because it could be very long.
  if (strstr(url, "data:application/dart;") == url) {
    url = "<data:application/dart>";
  }

  intptr_t line = -1;
  intptr_t column = -1;
  if (is_line) {
    ASSERT(token_pos_or_line.IsNoSource() || token_pos_or_line.IsReal());
    if (token_pos_or_line.IsReal()) {
      line = token_pos_or_line.Pos();
    }
  } else {
    ASSERT(!script.IsNull());
    script.GetTokenLocation(token_pos_or_line, &line, &column);
  }
  PrintSymbolicStackFrameIndex(buffer, frame_index);
  PrintSymbolicStackFrameBody(buffer, function_name, url, line, column);
}

static bool IsVisibleAsFutureListener(const Function& function) {
  if (function.is_visible()) {
    return true;
  }

  if (function.IsImplicitClosureFunction()) {
    return function.parent_function() == Function::null() ||
           Function::is_visible(function.parent_function());
  }

  return false;
}

#if defined(DART_PRECOMPILED_RUNTIME)
static void WriteImageBuildId(BaseTextBuffer* buffer,
                              const char* prefix,
                              uword image_address) {
  const auto& build_id = OS::GetAppBuildId(image_address);
  if (build_id.data != nullptr) {
    ASSERT(build_id.len > 0);
    buffer->AddString(prefix);
    buffer->AddString("'");
    for (intptr_t i = 0; i < build_id.len; i++) {
      buffer->Printf("%2.2x", build_id.data[i]);
    }
    buffer->AddString("'");
  }
}

void WriteStackTraceHeaderLoadingUnitEntry(BaseTextBuffer* buffer,
                                           intptr_t id,
                                           uword dso_base,
                                           uword instructions) {
  buffer->Printf("loading_unit: %" Pd "", id);
  WriteImageBuildId(buffer, ", build_id: ", instructions);
  buffer->Printf(", dso_base: %" Px ", instructions: %" Px "\n", dso_base,
                 instructions);
}
#endif

const char* StackTrace::ToCString() const {
  auto const T = Thread::Current();
  auto const zone = T->zone();
  auto& stack_trace = StackTrace::Handle(zone, this->ptr());
  auto& owner = Object::Handle(zone);
  auto& function = Function::Handle(zone);
  auto& code_object = Object::Handle(zone);
  auto& code = Code::Handle(zone);

#if defined(DART_PRECOMPILED_RUNTIME)
  const Array& loading_units =
      Array::Handle(T->isolate_group()->object_store()->loading_units());
  auto* const unit =
      loading_units.IsNull() ? nullptr : &LoadingUnit::Handle(zone);
#endif

  NoSafepointScope no_allocation;
  GrowableArray<const Function*> inlined_functions;
  GrowableArray<TokenPosition> inlined_token_positions;

#if defined(DART_PRECOMPILED_RUNTIME)
  GrowableArray<void*> addresses(10);
  const bool have_footnote_callback =
      FLAG_dwarf_stack_traces_mode &&
      Dart::dwarf_stacktrace_footnote_callback() != nullptr;
#endif

  ZoneTextBuffer buffer(zone, 1024);

#if defined(DART_PRECOMPILED_RUNTIME)
  auto const isolate_instructions = reinterpret_cast<uword>(
      T->isolate_group()->source()->snapshot_instructions);
#if defined(DEBUG)
  if (!loading_units.IsNull()) {
    *unit ^= loading_units.At(LoadingUnit::kRootId);
    ASSERT(!unit->IsNull());
    ASSERT(unit->has_instructions_image());
    ASSERT(reinterpret_cast<uword>(unit->instructions_image()) ==
           isolate_instructions);
  }
#endif
  auto const vm_instructions = reinterpret_cast<uword>(
      Dart::vm_isolate_group()->source()->snapshot_instructions);
  if (FLAG_dwarf_stack_traces_mode) {
    // This prologue imitates Android's debuggerd to make it possible to paste
    // the stack trace into ndk-stack.
    buffer.Printf(
        "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
    OSThread* thread = OSThread::Current();
    buffer.Printf("pid: %" Pd ", tid: %" Pd ", name %s\n", OS::ProcessId(),
                  OSThread::ThreadIdToIntPtr(thread->id()), thread->name());
#if defined(DART_COMPRESSED_POINTERS)
    const char kCompressedPointers[] = "yes";
#else
    const char kCompressedPointers[] = "no";
#endif
#if defined(DART_INCLUDE_SIMULATOR)
    const char kUsingSimulator[] = "yes";
#else
    const char kUsingSimulator[] = "no";
#endif
    buffer.Printf("os: %s arch: %s comp: %s sim: %s", kHostOperatingSystemName,
                  kTargetArchitectureName, kCompressedPointers,
                  kUsingSimulator);
    WriteImageBuildId(&buffer, "\nbuild_id: ", isolate_instructions);
    buffer.AddString("\n");
    if (!loading_units.IsNull()) {
      const intptr_t unit_count = loading_units.Length();
      for (intptr_t i = LoadingUnit::kRootId; i < unit_count; i++) {
        *unit ^= loading_units.At(i);
        if (!unit->has_instructions_image()) continue;
        const uword instructions =
            reinterpret_cast<uword>(unit->instructions_image());
        const uword dso_base = OS::GetAppDSOBase(instructions);
        WriteStackTraceHeaderLoadingUnitEntry(&buffer, i, dso_base,
                                              instructions);
      }
    }
    // Print the dso_base of the VM and isolate_instructions. We print both here
    // as the VM and isolate may be loaded from different snapshot images.
    const uword isolate_dso_base = OS::GetAppDSOBase(isolate_instructions);
    buffer.Printf("isolate_dso_base: %" Px "", isolate_dso_base);
    const uword vm_dso_base = OS::GetAppDSOBase(vm_instructions);
    buffer.Printf(", vm_dso_base: %" Px "\n", vm_dso_base);
    buffer.Printf("isolate_instructions: %" Px "", isolate_instructions);
    buffer.Printf(", vm_instructions: %" Px "\n", vm_instructions);
  }
#endif

  // Iterate through the stack frames and create C string description
  // for each frame.
  intptr_t frame_index = 0;
  uint32_t frame_skip = 0;
  // If we're already in a gap, don't print multiple gap markers.
  bool in_gap = false;
  do {
    for (intptr_t i = frame_skip; i < stack_trace.Length(); i++) {
      code_object = stack_trace.CodeAtFrame(i);
      if (code_object.IsNull()) {
        // Check for a null function, which indicates a gap in a StackOverflow
        // or OutOfMemory trace.
        if ((i < (stack_trace.Length() - 1)) &&
            (stack_trace.CodeAtFrame(i + 1) != Code::null())) {
          buffer.AddString("...\n...\n");
          // To account for gap frames.
          frame_index += stack_trace.PcOffsetAtFrame(i);
        }
        continue;
      }

      if (code_object.ptr() == StubCode::AsynchronousGapMarker().ptr()) {
        if (!in_gap) {
          buffer.AddString("<asynchronous suspension>\n");
        }
        in_gap = true;
        continue;
      }

      const uword pc_offset = stack_trace.PcOffsetAtFrame(i);

      // A visible frame ends any gap we might be in.
      in_gap = false;

#if defined(DART_DYNAMIC_MODULES)
      if (code_object.IsBytecode()) {
        const auto& bytecode = Bytecode::Cast(code_object);
        function = bytecode.function();

        if (!function.IsNull() &&
            (FLAG_show_invisible_frames || function.is_visible())) {
          auto const pos =
              bytecode.GetTokenIndexOfPC(bytecode.PayloadStart() + pc_offset);
          PrintSymbolicStackFrame(zone, &buffer, function, pos, frame_index);
          frame_index++;
        }
        continue;
      }
#endif  // defined(DART_DYNAMIC_MODULES)

      ASSERT(code_object.IsCode());
      code ^= code_object.ptr();
      ASSERT(code.IsFunctionCode());
      owner = code.owner();
      if (owner.IsFunction()) {
        function ^= owner.ptr();
      } else {
        function = Function::null();
      }
      const uword pc = code.PayloadStart() + pc_offset;

      const bool is_future_listener =
          pc_offset == StackTraceUtils::kFutureListenerPcOffset;

#if defined(DART_PRECOMPILED_RUNTIME)
      // When printing non-symbolic frames, we normally print call
      // addresses, not return addresses, by subtracting one from the PC to
      // get an address within the preceding instruction.
      //
      // The one exception is a normal closure registered as a listener on a
      // future. In this case, the returned pc_offset will be pointing to the
      // entry pooint of the function, which will be invoked when the future
      // completes. To make things more uniform stack unwinding code offets
      // pc_offset by 1 for such cases.
      const uword call_addr = pc - 1;

      if (FLAG_dwarf_stack_traces_mode) {
        if (have_footnote_callback) {
          addresses.Add(reinterpret_cast<void*>(call_addr));
        }

        // This output is formatted like Android's debuggerd. Note debuggerd
        // prints call addresses instead of return addresses.
        buffer.Printf("    #%02" Pd " abs %" Pp "", frame_index, call_addr);
        PrintNonSymbolicStackFrameBody(&buffer, call_addr, isolate_instructions,
                                       vm_instructions, loading_units, unit);
        frame_index++;
        continue;
      }

      if (function.IsNull()) {
        in_gap = false;
        // We can't print the symbolic information since the owner was not
        // retained, so instead print the static symbol + offset like the
        // non-symbolic stack traces.
        PrintSymbolicStackFrameIndex(&buffer, frame_index);
        PrintNonSymbolicStackFrameBody(&buffer, call_addr, isolate_instructions,
                                       vm_instructions, loading_units, unit);
        frame_index++;
        continue;
      }
#endif

      if (code.is_optimized() && stack_trace.expand_inlined() &&
          (FLAG_precompiled_mode || !is_future_listener)) {
        // Note: In AOT mode EmitFunctionEntrySourcePositionDescriptorIfNeeded
        // will take care of emitting a descriptor that would allow us to
        // symbolize stack frame with 0 offset.
        code.GetInlinedFunctionsAtReturnAddress(
            is_future_listener ? 0 : pc_offset, &inlined_functions,
            &inlined_token_positions);
        ASSERT(inlined_functions.length() >= 1);
        for (intptr_t j = inlined_functions.length() - 1; j >= 0; j--) {
          function = inlined_functions[j]->ptr();
          auto const pos = inlined_token_positions[j];
          if (is_future_listener && function.IsImplicitClosureFunction()) {
            function = function.parent_function();
          }
          if (FLAG_show_invisible_frames || function.is_visible()) {
            PrintSymbolicStackFrame(zone, &buffer, function, pos, frame_index,
                                    /*is_line=*/FLAG_precompiled_mode);
            frame_index++;
          }
        }
        continue;
      }

      if (FLAG_show_invisible_frames || function.is_visible() ||
          (is_future_listener && IsVisibleAsFutureListener(function))) {
        auto const pos = is_future_listener ? function.token_pos()
                                            : code.GetTokenIndexOfPC(pc);
        PrintSymbolicStackFrame(zone, &buffer, function, pos, frame_index);
        frame_index++;
      }
    }

    // Follow the link.
    frame_skip = stack_trace.skip_sync_start_in_parent_stack()
                     ? StackTrace::kSyncAsyncCroppedFrames
                     : 0;
    stack_trace = stack_trace.async_link();
  } while (!stack_trace.IsNull());

#if defined(DART_PRECOMPILED_RUNTIME)
  if (have_footnote_callback) {
    char* footnote = Dart::dwarf_stacktrace_footnote_callback()(
        &addresses[0], addresses.length());
    if (footnote != nullptr) {
      buffer.AddString(footnote);
      free(footnote);
    }
  }
#endif

  return buffer.buffer();
}

static void DwarfStackTracesHandler(bool value) {
  FLAG_dwarf_stack_traces_mode = value;

#if defined(PRODUCT)
  // We can safely remove function objects in precompiled snapshots if the
  // runtime will generate DWARF stack traces and we don't have runtime
  // debugging options like the VM service available.
  if (value) {
    FLAG_retain_function_objects = false;
    FLAG_retain_code_objects = false;
  }
#endif
}

DEFINE_FLAG_HANDLER(DwarfStackTracesHandler,
                    dwarf_stack_traces,
                    "Omit CodeSourceMaps in precompiled snapshots and don't "
                    "symbolize stack traces in the precompiled runtime.");

SuspendStatePtr SuspendState::New(intptr_t frame_size,
                                  const Instance& function_data,
                                  Heap::Space space) {
  ASSERT(frame_size >= 0);
  const intptr_t num_elements = frame_size + SuspendState::FrameSizeGrowthGap();
#if !defined(DART_PRECOMPILED_RUNTIME)
  // Include heap object alignment overhead into the frame capacity.
  const intptr_t instance_size = SuspendState::InstanceSize(num_elements);
  const intptr_t frame_capacity =
      instance_size - SuspendState::payload_offset();
  ASSERT(SuspendState::InstanceSize(frame_capacity) == instance_size);
  ASSERT(frame_size <= frame_capacity);
#endif
  auto raw = Object::Allocate<SuspendState>(space, num_elements);
  NoSafepointScope no_safepoint;
  ASSERT_EQUAL(raw->untag()->pc_, 0);
#if !defined(DART_PRECOMPILED_RUNTIME)
  raw->untag()->frame_capacity_ = frame_capacity;
#endif
  raw->untag()->frame_size_ = frame_size;
  raw->untag()->set_function_data(function_data.ptr());
  return raw;
}

SuspendStatePtr SuspendState::Clone(Thread* thread,
                                    const SuspendState& src,
                                    Heap::Space space) {
  ASSERT(src.pc() != 0);
  Zone* zone = thread->zone();
  const intptr_t frame_size = src.frame_size();
  const SuspendState& dst = SuspendState::Handle(
      zone,
      SuspendState::New(frame_size, Instance::Handle(zone, src.function_data()),
                        space));
  dst.set_then_callback(Closure::Handle(zone, src.then_callback()));
  dst.set_error_callback(Closure::Handle(zone, src.error_callback()));
  {
    NoSafepointScope no_safepoint;
    memmove(dst.payload(), src.payload(), frame_size);
    // Update value of :suspend_state variable in the copied frame.
    const uword fp = reinterpret_cast<uword>(dst.payload() + frame_size);
    *reinterpret_cast<ObjectPtr*>(
        LocalVarAddress(fp, runtime_frame_layout.FrameSlotForVariableIndex(
                                kSuspendStateVarIndex))) = dst.ptr();
    dst.set_pc(src.pc());
    // Trigger write barrier if needed.
    if (dst.ptr()->IsOldObject()) {
      dst.untag()->EnsureInRememberedSet(thread);
    }
    if (thread->is_marking()) {
      thread->DeferredMarkingStackAddObject(dst.ptr());
    }
  }
  return dst.ptr();
}

#if !defined(DART_PRECOMPILED_RUNTIME)
void SuspendState::set_frame_capacity(intptr_t frame_capcity) const {
  ASSERT(frame_capcity >= 0);
  StoreNonPointer(&untag()->frame_capacity_, frame_capcity);
}
#endif

void SuspendState::set_frame_size(intptr_t frame_size) const {
  ASSERT(frame_size >= 0);
  StoreNonPointer(&untag()->frame_size_, frame_size);
}

void SuspendState::set_pc(uword pc) const {
  StoreNonPointer(&untag()->pc_, pc);
}

void SuspendState::set_function_data(const Instance& function_data) const {
  untag()->set_function_data(function_data.ptr());
}

void SuspendState::set_then_callback(const Closure& then_callback) const {
  untag()->set_then_callback(then_callback.ptr());
}

void SuspendState::set_error_callback(const Closure& error_callback) const {
  untag()->set_error_callback(error_callback.ptr());
}

const char* SuspendState::ToCString() const {
  return "SuspendState";
}

CodePtr SuspendState::GetCodeObject() const {
  ASSERT(pc() != 0);
#if defined(DART_PRECOMPILED_RUNTIME)
  NoSafepointScope no_safepoint;
  CodePtr code = ReversePc::Lookup(IsolateGroup::Current(), pc(),
                                   /*is_return_address=*/true);
  ASSERT(code != Code::null());
  return code;
#else
  ObjectPtr code = *(reinterpret_cast<ObjectPtr*>(
      untag()->payload() + untag()->frame_size_ +
      runtime_frame_layout.code_from_fp * kWordSize));
  return Code::RawCast(code);
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

void RegExp::set_pattern(const String& pattern) const {
  untag()->set_pattern(pattern.ptr());
}

void RegExp::set_function(intptr_t cid,
                          bool sticky,
                          const Function& value) const {
  if (sticky) {
    switch (cid) {
      case kOneByteStringCid:
        return untag()->set_one_byte_sticky(value.ptr());
      case kTwoByteStringCid:
        return untag()->set_two_byte_sticky(value.ptr());
    }
  } else {
    switch (cid) {
      case kOneByteStringCid:
        return untag()->set_one_byte(value.ptr());
      case kTwoByteStringCid:
        return untag()->set_two_byte(value.ptr());
    }
  }
}

void RegExp::set_bytecode(bool is_one_byte,
                          bool sticky,
                          const TypedData& bytecode) const {
  if (sticky) {
    if (is_one_byte) {
      untag()->set_one_byte_sticky<std::memory_order_release>(bytecode.ptr());
    } else {
      untag()->set_two_byte_sticky<std::memory_order_release>(bytecode.ptr());
    }
  } else {
    if (is_one_byte) {
      untag()->set_one_byte<std::memory_order_release>(bytecode.ptr());
    } else {
      untag()->set_two_byte<std::memory_order_release>(bytecode.ptr());
    }
  }
}

void RegExp::set_num_bracket_expressions(intptr_t value) const {
  untag()->num_bracket_expressions_ = value;
}

void RegExp::set_capture_name_map(const Array& array) const {
  untag()->set_capture_name_map(array.ptr());
}

RegExpPtr RegExp::New(Zone* zone, Heap::Space space) {
  const auto& result = RegExp::Handle(Object::Allocate<RegExp>(space));
  ASSERT_EQUAL(result.type(), kUninitialized);
  ASSERT(result.flags() == RegExpFlags());
  result.set_num_bracket_expressions(-1);
  result.set_num_registers(/*is_one_byte=*/false, -1);
  result.set_num_registers(/*is_one_byte=*/true, -1);

  if (!FLAG_interpret_irregexp) {
    auto thread = Thread::Current();
    const Library& lib = Library::Handle(zone, Library::CoreLibrary());
    const Class& owner =
        Class::Handle(zone, lib.LookupClass(Symbols::RegExp()));

    for (intptr_t cid = kOneByteStringCid; cid <= kTwoByteStringCid; cid++) {
      CreateSpecializedFunction(thread, zone, result, cid, /*sticky=*/false,
                                owner);
      CreateSpecializedFunction(thread, zone, result, cid, /*sticky=*/true,
                                owner);
    }
  }
  return result.ptr();
}

const char* RegExpFlags::ToCString() const {
  switch (value_ & ~kGlobal) {
    case kIgnoreCase | kMultiLine | kDotAll | kUnicode:
      return "imsu";
    case kIgnoreCase | kMultiLine | kDotAll:
      return "ims";
    case kIgnoreCase | kMultiLine | kUnicode:
      return "imu";
    case kIgnoreCase | kUnicode | kDotAll:
      return "ius";
    case kMultiLine | kDotAll | kUnicode:
      return "msu";
    case kIgnoreCase | kMultiLine:
      return "im";
    case kIgnoreCase | kDotAll:
      return "is";
    case kIgnoreCase | kUnicode:
      return "iu";
    case kMultiLine | kDotAll:
      return "ms";
    case kMultiLine | kUnicode:
      return "mu";
    case kDotAll | kUnicode:
      return "su";
    case kIgnoreCase:
      return "i";
    case kMultiLine:
      return "m";
    case kDotAll:
      return "s";
    case kUnicode:
      return "u";
    default:
      break;
  }
  return "";
}

bool RegExp::CanonicalizeEquals(const Instance& other) const {
  if (this->ptr() == other.ptr()) {
    return true;  // "===".
  }
  if (other.IsNull() || !other.IsRegExp()) {
    return false;
  }
  const RegExp& other_js = RegExp::Cast(other);
  // Match the pattern.
  const String& str1 = String::Handle(pattern());
  const String& str2 = String::Handle(other_js.pattern());
  if (!str1.Equals(str2)) {
    return false;
  }
  // Match the flags.
  if (flags() != other_js.flags()) {
    return false;
  }
  return true;
}

uint32_t RegExp::CanonicalizeHash() const {
  // Must agree with RegExpKey::Hash.
  return CombineHashes(String::Hash(pattern()), flags().value());
}

const char* RegExp::ToCString() const {
  const String& str = String::Handle(pattern());
  return OS::SCreate(Thread::Current()->zone(), "RegExp: pattern=%s flags=%s",
                     str.ToCString(), flags().ToCString());
}

WeakPropertyPtr WeakProperty::New(Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->weak_property_class() !=
         Class::null());
  return Object::Allocate<WeakProperty>(space);
}

const char* WeakProperty::ToCString() const {
  return "_WeakProperty";
}

WeakReferencePtr WeakReference::New(Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->weak_reference_class() !=
         Class::null());
  return Object::Allocate<WeakReference>(space);
}
const char* WeakReference::ToCString() const {
  TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
  String& type_args_name = String::Handle(type_args.UserVisibleName());
  return OS::SCreate(Thread::Current()->zone(), "_WeakReference%s",
                     type_args_name.ToCString());
}

const char* FinalizerBase::ToCString() const {
  return "FinalizerBase";
}

FinalizerPtr Finalizer::New(Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->finalizer_class() !=
         Class::null());
  ASSERT(
      Class::Handle(IsolateGroup::Current()->object_store()->finalizer_class())
          .EnsureIsAllocateFinalized(Thread::Current()) == Error::null());
  return Object::Allocate<Finalizer>(space);
}

const char* Finalizer::ToCString() const {
  TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
  String& type_args_name = String::Handle(type_args.UserVisibleName());
  return OS::SCreate(Thread::Current()->zone(), "_FinalizerImpl%s",
                     type_args_name.ToCString());
}

NativeFinalizerPtr NativeFinalizer::New(Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->native_finalizer_class() !=
         Class::null());
  ASSERT(Class::Handle(
             IsolateGroup::Current()->object_store()->native_finalizer_class())
             .EnsureIsAllocateFinalized(Thread::Current()) == Error::null());
  return Object::Allocate<NativeFinalizer>(space);
}

// Runs the finalizer if not detached, detaches the value and set external size
// to 0.
// TODO(http://dartbug.com/47777): Can this be merged with
// RunNativeFinalizerCallback?
void NativeFinalizer::RunCallback(const FinalizerEntry& entry,
                                  const char* trace_context) const {
  Thread* const thread = Thread::Current();
  Zone* const zone = thread->zone();
  IsolateGroup* const group = thread->isolate_group();
  const intptr_t external_size = entry.external_size();
  const auto& token_object = Object::Handle(zone, entry.token());
  const auto& callback_pointer = Pointer::Handle(zone, this->callback());
  const auto callback = reinterpret_cast<NativeFinalizer::Callback>(
      callback_pointer.NativeAddress());
  if (token_object.IsFinalizerEntry()) {
    // Detached from Dart code.
    ASSERT(token_object.ptr() == entry.ptr());
    ASSERT(external_size == 0);
    if (FLAG_trace_finalizers) {
      THR_Print(
          "%s: Not running native finalizer %p callback %p, "
          "detached\n",
          trace_context, ptr()->untag(), callback);
    }
  } else {
    const auto& token = Pointer::Cast(token_object);
    void* peer = reinterpret_cast<void*>(token.NativeAddress());
    if (FLAG_trace_finalizers) {
      THR_Print(
          "%s: Running native finalizer %p callback %p "
          "with token %p\n",
          trace_context, ptr()->untag(), callback, peer);
    }
    entry.set_token(entry);
    callback(peer);
    if (external_size > 0) {
      ASSERT(!entry.value()->IsSmi());
      Heap::Space space =
          entry.value()->IsOldObject() ? Heap::kOld : Heap::kNew;
      if (FLAG_trace_finalizers) {
        THR_Print("%s: Clearing external size %" Pd " bytes in %s space\n",
                  trace_context, external_size, space == 0 ? "new" : "old");
      }
      group->heap()->FreedExternal(external_size, space);
      entry.set_external_size(0);
    }
  }
}

const char* NativeFinalizer::ToCString() const {
  const auto& pointer = Pointer::Handle(callback());
  return OS::SCreate(Thread::Current()->zone(), "_NativeFinalizer %s",
                     pointer.ToCString());
}

FinalizerEntryPtr FinalizerEntry::New(const FinalizerBase& finalizer,
                                      Heap::Space space) {
  ASSERT(IsolateGroup::Current()->object_store()->finalizer_entry_class() !=
         Class::null());
  const auto& entry =
      FinalizerEntry::Handle(Object::Allocate<FinalizerEntry>(space));
  ASSERT_EQUAL(entry.external_size(), 0);
  entry.set_finalizer(finalizer);
  return entry.ptr();
}

void FinalizerEntry::set_finalizer(const FinalizerBase& value) const {
  untag()->set_finalizer(value.ptr());
}

const char* FinalizerEntry::ToCString() const {
  return "FinalizerEntry";
}

AbstractTypePtr MirrorReference::GetAbstractTypeReferent() const {
  ASSERT(Object::Handle(referent()).IsAbstractType());
  return AbstractType::Cast(Object::Handle(referent())).ptr();
}

ClassPtr MirrorReference::GetClassReferent() const {
  ASSERT(Object::Handle(referent()).IsClass());
  return Class::Cast(Object::Handle(referent())).ptr();
}

FieldPtr MirrorReference::GetFieldReferent() const {
  ASSERT(Object::Handle(referent()).IsField());
  return Field::Cast(Object::Handle(referent())).ptr();
}

FunctionPtr MirrorReference::GetFunctionReferent() const {
  ASSERT(Object::Handle(referent()).IsFunction());
  return Function::Cast(Object::Handle(referent())).ptr();
}

FunctionTypePtr MirrorReference::GetFunctionTypeReferent() const {
  ASSERT(Object::Handle(referent()).IsFunctionType());
  return FunctionType::Cast(Object::Handle(referent())).ptr();
}

LibraryPtr MirrorReference::GetLibraryReferent() const {
  ASSERT(Object::Handle(referent()).IsLibrary());
  return Library::Cast(Object::Handle(referent())).ptr();
}

TypeParameterPtr MirrorReference::GetTypeParameterReferent() const {
  ASSERT(Object::Handle(referent()).IsTypeParameter());
  return TypeParameter::Cast(Object::Handle(referent())).ptr();
}

MirrorReferencePtr MirrorReference::New(const Object& referent,
                                        Heap::Space space) {
  const auto& result =
      MirrorReference::Handle(Object::Allocate<MirrorReference>(space));
  result.set_referent(referent);
  return result.ptr();
}

const char* MirrorReference::ToCString() const {
  return "_MirrorReference";
}

UserTagPtr UserTag::MakeActive() const {
  Isolate* isolate = Isolate::Current();
  ASSERT(isolate != nullptr);
  UserTag& old = UserTag::Handle(isolate->current_tag());
  isolate->set_current_tag(*this);

#if !defined(PRODUCT)
  // Notify VM service clients that the current UserTag has changed.
  if (Service::profiler_stream.enabled()) {
    ServiceEvent event(isolate, ServiceEvent::kUserTagChanged);
    String& name = String::Handle(old.label());
    event.set_previous_tag(name.ToCString());
    name ^= label();
    event.set_updated_tag(name.ToCString());
    Service::HandleEvent(&event);
  }
#endif  // !defined(PRODUCT)

  return old.ptr();
}

UserTagPtr UserTag::New(const String& label, Heap::Space space) {
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  ASSERT(isolate->tag_table() != GrowableObjectArray::null());
  // Canonicalize by name.
  UserTag& result = UserTag::Handle(FindTagInIsolate(thread, label));
  if (!result.IsNull()) {
    // Tag already exists, return existing instance.
    return result.ptr();
  }
  if (TagTableIsFull(thread)) {
    const String& error = String::Handle(String::NewFormatted(
        "UserTag instance limit (%" Pd ") reached.", UserTags::kMaxUserTags));
    const Array& args = Array::Handle(Array::New(1));
    args.SetAt(0, error);
    Exceptions::ThrowByType(Exceptions::kUnsupported, args);
  }
  // No tag with label exists, create and register with isolate tag table.
  result = Object::Allocate<UserTag>(space);
  result.set_label(label);
  result.set_streamable(UserTags::IsTagNameStreamable(label.ToCString()));
  AddTagToIsolate(thread, result);
  return result.ptr();
}

UserTagPtr UserTag::DefaultTag() {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Isolate* isolate = thread->isolate();
  ASSERT(isolate != nullptr);
  if (isolate->default_tag() != UserTag::null()) {
    // Already created.
    return isolate->default_tag();
  }
  // Create default tag.
  const UserTag& result =
      UserTag::Handle(zone, UserTag::New(Symbols::Default()));
  ASSERT(result.tag() == UserTags::kDefaultUserTag);
  isolate->set_default_tag(result);
  return result.ptr();
}

UserTagPtr UserTag::FindTagInIsolate(Isolate* isolate,
                                     Thread* thread,
                                     const String& label) {
  Zone* zone = thread->zone();
  if (isolate->tag_table() == GrowableObjectArray::null()) {
    return UserTag::null();
  }
  const GrowableObjectArray& tag_table =
      GrowableObjectArray::Handle(zone, isolate->tag_table());
  UserTag& other = UserTag::Handle(zone);
  String& tag_label = String::Handle(zone);
  for (intptr_t i = 0; i < tag_table.Length(); i++) {
    other ^= tag_table.At(i);
    ASSERT(!other.IsNull());
    tag_label = other.label();
    ASSERT(!tag_label.IsNull());
    if (tag_label.Equals(label)) {
      return other.ptr();
    }
  }
  return UserTag::null();
}

UserTagPtr UserTag::FindTagInIsolate(Thread* thread, const String& label) {
  Isolate* isolate = thread->isolate();
  return FindTagInIsolate(isolate, thread, label);
}

void UserTag::AddTagToIsolate(Thread* thread, const UserTag& tag) {
  Isolate* isolate = thread->isolate();
  Zone* zone = thread->zone();
  ASSERT(isolate->tag_table() != GrowableObjectArray::null());
  const GrowableObjectArray& tag_table =
      GrowableObjectArray::Handle(zone, isolate->tag_table());
  ASSERT(!TagTableIsFull(thread));
#if defined(DEBUG)
  // Verify that no existing tag has the same tag id.
  UserTag& other = UserTag::Handle(thread->zone());
  for (intptr_t i = 0; i < tag_table.Length(); i++) {
    other ^= tag_table.At(i);
    ASSERT(!other.IsNull());
    ASSERT(tag.tag() != other.tag());
  }
#endif
  // Generate the UserTag tag id by taking the length of the isolate's
  // tag table + kUserTagIdOffset.
  uword tag_id = tag_table.Length() + UserTags::kUserTagIdOffset;
  ASSERT(tag_id >= UserTags::kUserTagIdOffset);
  ASSERT(tag_id < (UserTags::kUserTagIdOffset + UserTags::kMaxUserTags));
  tag.set_tag(tag_id);
  tag_table.Add(tag);
}

bool UserTag::TagTableIsFull(Thread* thread) {
  Isolate* isolate = thread->isolate();
  ASSERT(isolate->tag_table() != GrowableObjectArray::null());
  const GrowableObjectArray& tag_table =
      GrowableObjectArray::Handle(thread->zone(), isolate->tag_table());
  ASSERT(tag_table.Length() <= UserTags::kMaxUserTags);
  return tag_table.Length() == UserTags::kMaxUserTags;
}

UserTagPtr UserTag::FindTagById(const Isolate* isolate, uword tag_id) {
  ASSERT(isolate != nullptr);
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  ASSERT(isolate->tag_table() != GrowableObjectArray::null());
  const GrowableObjectArray& tag_table =
      GrowableObjectArray::Handle(zone, isolate->tag_table());
  UserTag& tag = UserTag::Handle(zone);
  for (intptr_t i = 0; i < tag_table.Length(); i++) {
    tag ^= tag_table.At(i);
    if (tag.tag() == tag_id) {
      return tag.ptr();
    }
  }
  return UserTag::null();
}

const char* UserTag::ToCString() const {
  const String& tag_label = String::Handle(label());
  return tag_label.ToCString();
}

void DumpTypeTable(Isolate* isolate) {
  OS::PrintErr("canonical types:\n");
  CanonicalTypeSet table(isolate->group()->object_store()->canonical_types());
  table.Dump();
  table.Release();
}

void DumpFunctionTypeTable(Isolate* isolate) {
  OS::PrintErr("canonical function types:\n");
  CanonicalFunctionTypeSet table(
      isolate->group()->object_store()->canonical_function_types());
  table.Dump();
  table.Release();
}

void DumpRecordTypeTable(Isolate* isolate) {
  OS::PrintErr("canonical record types:\n");
  CanonicalRecordTypeSet table(
      isolate->group()->object_store()->canonical_record_types());
  table.Dump();
  table.Release();
}

void DumpTypeParameterTable(Isolate* isolate) {
  OS::PrintErr("canonical type parameters (cloned from declarations):\n");
  CanonicalTypeParameterSet table(
      isolate->group()->object_store()->canonical_type_parameters());
  table.Dump();
  table.Release();
}

void DumpTypeArgumentsTable(Isolate* isolate) {
  OS::PrintErr("canonical type arguments:\n");
  CanonicalTypeArgumentsSet table(
      isolate->group()->object_store()->canonical_type_arguments());
  table.Dump();
  table.Release();
}

EntryPointPragma FindEntryPointPragma(IsolateGroup* IG,
                                      const Array& metadata,
                                      Field* reusable_field_handle,
                                      Object* pragma) {
  for (intptr_t i = 0; i < metadata.Length(); i++) {
    *pragma = metadata.At(i);
    if (pragma->clazz() != IG->object_store()->pragma_class()) {
      continue;
    }
    *reusable_field_handle = IG->object_store()->pragma_name();
    const auto pragma_name =
        Instance::Cast(*pragma).GetField(*reusable_field_handle);
    if ((pragma_name != Symbols::vm_entry_point().ptr()) &&
        (pragma_name != Symbols::dyn_module_callable().ptr()) &&
        (pragma_name != Symbols::dyn_module_implicitly_callable().ptr()) &&
        (pragma_name != Symbols::dyn_module_extendable().ptr())) {
      continue;
    }
    *reusable_field_handle = IG->object_store()->pragma_options();
    *pragma = Instance::Cast(*pragma).GetField(*reusable_field_handle);
    if (pragma->ptr() == Bool::null() || pragma->ptr() == Bool::True().ptr()) {
      return EntryPointPragma::kAlways;
      break;
    }
    if (pragma->ptr() == Symbols::get().ptr()) {
      return EntryPointPragma::kGetterOnly;
    }
    if (pragma->ptr() == Symbols::set().ptr()) {
      return EntryPointPragma::kSetterOnly;
    }
    if (pragma->ptr() == Symbols::call().ptr()) {
      return EntryPointPragma::kCallOnly;
    }
  }
  return EntryPointPragma::kNever;
}

#if !defined(DART_PRECOMPILED_RUNTIME)
// Note: see also [NeedsDynamicInvocationForwarder] which ensures that we
// never land in a function which expects parameters in registers from a
// dynamic call site.
intptr_t Function::MaxNumberOfParametersInRegisters(Zone* zone) const {
#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64) ||                  \
    defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_RISCV32) ||                \
    defined(TARGET_ARCH_RISCV64)
  if (!FLAG_precompiled_mode) {
    return 0;
  }

  if (!FLAG_use_register_cc) {
    return 0;
  }

  if (IsGeneric()) {
    return 0;
  }

  switch (kind()) {
    case UntaggedFunction::kClosureFunction:
    case UntaggedFunction::kImplicitClosureFunction:
    case UntaggedFunction::kNoSuchMethodDispatcher:
    case UntaggedFunction::kInvokeFieldDispatcher:
    case UntaggedFunction::kDynamicInvocationForwarder:
    case UntaggedFunction::kMethodExtractor:
    case UntaggedFunction::kFfiTrampoline:
    case UntaggedFunction::kFieldInitializer:
    case UntaggedFunction::kIrregexpFunction:
      return 0;

    default:
      break;
  }

  const auto unboxing_metadata = kernel::UnboxingInfoMetadataOf(*this, zone);
  if (unboxing_metadata != nullptr &&
      unboxing_metadata->must_use_stack_calling_convention) {
    return 0;
  }

  // Getters and setters have fixed signatures.
  switch (kind()) {
    case UntaggedFunction::kGetterFunction:
    case UntaggedFunction::kImplicitGetter:
    case UntaggedFunction::kSetterFunction:
    case UntaggedFunction::kImplicitSetter:
      return num_fixed_parameters();

    default:
      break;
  }

  if (unboxing_metadata != nullptr &&
      unboxing_metadata->has_overrides_with_less_direct_parameters) {
    // Receiver (`this`) can always be passed in the register because it is
    // never an optional or named parameter.
    return unboxing_metadata->unboxed_args_info.length() + 1;
  }

  return num_fixed_parameters();
#endif
  return 0;
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

ErrorPtr Function::VerifyEntryPoint(EntryPointPragma pragma) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  const Library& lib = Library::Handle();
#else
  const Class& cls = Class::Handle(Owner());
  const Library& lib = Library::Handle(cls.library());
#endif
  return dart::VerifyEntryPoint(lib, *this, *this, pragma);
}

ErrorPtr Field::VerifyEntryPoint(EntryPointPragma pragma) const {
#if defined(DART_PRECOMPILED_RUNTIME)
  const Library& lib = Library::Handle();
#else
  const Class& cls = Class::Handle(Owner());
  const Library& lib = Library::Handle(cls.library());
#endif
  return dart::VerifyEntryPoint(lib, *this, *this, pragma);
}

ErrorPtr Class::VerifyEntryPoint() const {
#if defined(DART_PRECOMPILED_RUNTIME)
  const Library& lib = Library::Handle();
#else
  const Library& lib = Library::Handle(library());
  if (lib.IsNull()) return Error::null();
#endif
  return dart::VerifyEntryPoint(lib, *this, *this, EntryPointPragma::kAlways);
}

AbstractTypePtr RecordType::FieldTypeAt(intptr_t index) const {
  const Array& field_types = Array::Handle(untag()->field_types());
  return AbstractType::RawCast(field_types.At(index));
}

void RecordType::SetFieldTypeAt(intptr_t index,
                                const AbstractType& value) const {
  ASSERT(!value.IsNull());
  const Array& field_types = Array::Handle(untag()->field_types());
  field_types.SetAt(index, value);
}

void RecordType::set_field_types(const Array& value) const {
  ASSERT(!value.IsNull());
  untag()->set_field_types(value.ptr());
}

void RecordType::set_shape(RecordShape shape) const {
  untag()->set_shape(shape.AsSmi());
}

ArrayPtr RecordType::GetFieldNames(Thread* thread) const {
  return shape().GetFieldNames(thread);
}

void RecordType::Print(NameVisibility name_visibility,
                       BaseTextBuffer* printer) const {
  if (IsNull()) {
    printer->AddString("null");
    return;
  }
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  AbstractType& type = AbstractType::Handle(zone);
  String& name = String::Handle(zone);
  const intptr_t num_fields = NumFields();
  const Array& field_names = Array::Handle(zone, GetFieldNames(thread));
  const intptr_t num_positional_fields = num_fields - field_names.Length();
  printer->AddString("(");
  for (intptr_t i = 0; i < num_fields; ++i) {
    if (i != 0) {
      printer->AddString(", ");
    }
    if (i == num_positional_fields) {
      printer->AddString("{");
    }
    type = FieldTypeAt(i);
    type.PrintName(name_visibility, printer);
    if (i >= num_positional_fields) {
      printer->AddString(" ");
      name ^= field_names.At(i - num_positional_fields);
      printer->AddString(name.ToCString());
    }
  }
  if (num_positional_fields < num_fields) {
    printer->AddString("}");
  }
  printer->AddString(")");
  printer->AddString(NullabilitySuffix(name_visibility));
}

const char* RecordType::ToCString() const {
  Zone* zone = Thread::Current()->zone();
  ZoneTextBuffer printer(zone);
  Print(kInternalName, &printer);
  return printer.buffer();
}

bool RecordType::IsInstantiated(Genericity genericity,
                                intptr_t num_free_fun_type_params) const {
  AbstractType& type = AbstractType::Handle();
  const intptr_t num_fields = NumFields();
  for (intptr_t i = 0; i < num_fields; ++i) {
    type = FieldTypeAt(i);
    if (!type.IsInstantiated(genericity, num_free_fun_type_params)) {
      return false;
    }
  }
  return true;
}

RecordTypePtr RecordType::New(Heap::Space space) {
  return Object::Allocate<RecordType>(space);
}

RecordTypePtr RecordType::New(RecordShape shape,
                              const Array& field_types,
                              Nullability nullability,
                              Heap::Space space) {
  Zone* Z = Thread::Current()->zone();
  const RecordType& result = RecordType::Handle(Z, RecordType::New(space));
  result.set_shape(shape);
  result.set_field_types(field_types);
  result.SetHash(0);
  result.set_flags(0);
  result.set_nullability(nullability);
  result.set_type_state(UntaggedAbstractType::kAllocated);
  result.InitializeTypeTestingStubNonAtomic(
      Code::Handle(Z, TypeTestingStubGenerator::DefaultCodeForType(result)));
  return result.ptr();
}

RecordTypePtr RecordType::ToNullability(Nullability value,
                                        Heap::Space space) const {
  if (nullability() == value) {
    return ptr();
  }
  // Clone record type and set new nullability.
  // Always cloning in old space and removing space parameter would not satisfy
  // currently existing requests for type instantiation in new space.
  Thread* T = Thread::Current();
  Zone* Z = T->zone();
  AbstractType& type = RecordType::Handle(
      Z,
      RecordType::New(shape(), Array::Handle(Z, field_types()), value, space));
  if (IsFinalized()) {
    type.SetIsFinalized();
    if (IsCanonical()) {
      type ^= type.Canonicalize(T);
    }
  }
  return RecordType::Cast(type).ptr();
}

bool RecordType::IsEquivalent(
    const Instance& other,
    TypeEquality kind,
    FunctionTypeMapping* function_type_equivalence) const {
  ASSERT(!IsNull());
  if (ptr() == other.ptr()) {
    return true;
  }
  if (!other.IsRecordType()) {
    return false;
  }
  const RecordType& other_type = RecordType::Cast(other);
  // Equal record types must have the same shape
  // (number of fields and named fields).
  if (shape() != other_type.shape()) {
    return false;
  }
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  if (!IsNullabilityEquivalent(thread, other_type, kind)) {
    return false;
  }
  // Equal record types must have equal field types.
  AbstractType& field_type = Type::Handle(zone);
  AbstractType& other_field_type = Type::Handle(zone);
  const intptr_t num_fields = NumFields();
  for (intptr_t i = 0; i < num_fields; ++i) {
    field_type = FieldTypeAt(i);
    other_field_type = other_type.FieldTypeAt(i);
    if (!field_type.IsEquivalent(other_field_type, kind,
                                 function_type_equivalence)) {
      return false;
    }
  }
  return true;
}

uword RecordType::ComputeHash() const {
  ASSERT(IsFinalized());
  uint32_t result = 0;
  result = CombineHashes(result, static_cast<uint32_t>(nullability()));
  result = CombineHashes(result, static_cast<uint32_t>(shape().AsInt()));
  AbstractType& type = AbstractType::Handle();
  const intptr_t num_fields = NumFields();
  for (intptr_t i = 0; i < num_fields; ++i) {
    type = FieldTypeAt(i);
    result = CombineHashes(result, type.Hash());
  }
  result = FinalizeHash(result, kHashBits);
  SetHash(result);
  return result;
}

AbstractTypePtr RecordType::Canonicalize(Thread* thread) const {
  ASSERT(IsFinalized());
  Zone* zone = thread->zone();
  AbstractType& type = AbstractType::Handle(zone);
  if (IsCanonical()) {
#ifdef DEBUG
    // Verify that all fields are allocated in old space and are canonical.
    ASSERT(Array::Handle(zone, field_types()).IsOld());
    const intptr_t num_fields = NumFields();
    for (intptr_t i = 0; i < num_fields; ++i) {
      type = FieldTypeAt(i);
      ASSERT(type.IsOld());
      ASSERT(type.IsCanonical());
    }
#endif
    return ptr();
  }
  auto isolate_group = thread->isolate_group();
  ObjectStore* object_store = isolate_group->object_store();
  RecordType& rec = RecordType::Handle(zone);
  {
    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
    CanonicalRecordTypeSet table(zone, object_store->canonical_record_types());
    rec ^= table.GetOrNull(CanonicalRecordTypeKey(*this));
    ASSERT(object_store->canonical_record_types() == table.Release().ptr());
  }
  if (rec.IsNull()) {
    ASSERT(Array::Handle(zone, field_types()).IsOld());
    const intptr_t num_fields = NumFields();
    for (intptr_t i = 0; i < num_fields; ++i) {
      type = FieldTypeAt(i);
      if (!type.IsCanonical()) {
        type = type.Canonicalize(thread);
        SetFieldTypeAt(i, type);
      }
    }
    // Check to see if the record type got added to canonical table as part
    // of the canonicalization of its signature types.
    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
    CanonicalRecordTypeSet table(zone, object_store->canonical_record_types());
    rec ^= table.GetOrNull(CanonicalRecordTypeKey(*this));
    if (rec.IsNull()) {
      // Add this record type into the canonical table of record types.
      if (this->IsNew()) {
        rec ^= Object::Clone(*this, Heap::kOld);
      } else {
        rec = this->ptr();
      }
      ASSERT(rec.IsOld());
      rec.SetCanonical();  // Mark object as being canonical.
      bool present = table.Insert(rec);
      ASSERT(!present);
    }
    object_store->set_canonical_record_types(table.Release());
  }
  return rec.ptr();
}

void RecordType::EnumerateURIs(URIs* uris) const {
  AbstractType& type = AbstractType::Handle();
  const intptr_t num_fields = NumFields();
  for (intptr_t i = 0; i < num_fields; ++i) {
    type = FieldTypeAt(i);
    type.EnumerateURIs(uris);
  }
}

void RecordType::PrintName(NameVisibility name_visibility,
                           BaseTextBuffer* printer) const {
  RecordType::Cast(*this).Print(name_visibility, printer);
}

AbstractTypePtr RecordType::InstantiateFrom(
    const TypeArguments& instantiator_type_arguments,
    const TypeArguments& function_type_arguments,
    intptr_t num_free_fun_type_params,
    Heap::Space space,
    FunctionTypeMapping* function_type_mapping,
    intptr_t num_parent_type_args_adjustment) const {
  ASSERT(IsFinalized());
  Zone* zone = Thread::Current()->zone();

  const intptr_t num_fields = NumFields();
  const Array& old_field_types = Array::Handle(zone, field_types());
  const Array& new_field_types =
      Array::Handle(zone, Array::New(num_fields, space));
  AbstractType& type = AbstractType::Handle(zone);
  for (intptr_t i = 0; i < num_fields; ++i) {
    type ^= old_field_types.At(i);
    if (!type.IsInstantiated()) {
      type = type.InstantiateFrom(
          instantiator_type_arguments, function_type_arguments,
          num_free_fun_type_params, space, function_type_mapping,
          num_parent_type_args_adjustment);
      // A returned null type indicates a failed instantiation in dead code that
      // must be propagated up to the caller, the optimizing compiler.
      if (type.IsNull()) {
        return RecordType::null();
      }
    }
    new_field_types.SetAt(i, type);
  }

  const auto& rec = RecordType::Handle(
      zone, RecordType::New(shape(), new_field_types, nullability(), space));

  rec.SetIsFinalized();

  // Canonicalization is not part of instantiation.
  return rec.ptr();
}

AbstractTypePtr RecordType::UpdateFunctionTypes(
    intptr_t num_parent_type_args_adjustment,
    intptr_t num_free_fun_type_params,
    Heap::Space space,
    FunctionTypeMapping* function_type_mapping) const {
  ASSERT(IsFinalized());
  ASSERT(num_parent_type_args_adjustment >= 0);
  Zone* zone = Thread::Current()->zone();
  const auto& types = Array::Handle(zone, field_types());
  Array* updated_types = nullptr;
  auto& type = AbstractType::Handle(zone);
  auto& updated = AbstractType::Handle(zone);
  for (intptr_t i = 0, n = NumFields(); i < n; ++i) {
    type ^= types.At(i);
    updated = type.UpdateFunctionTypes(num_parent_type_args_adjustment,
                                       num_free_fun_type_params, space,
                                       function_type_mapping);
    if (type.ptr() != updated.ptr()) {
      if (updated_types == nullptr) {
        updated_types = &Array::Handle(zone, Array::New(n, space));
        for (intptr_t j = 0; j < i; ++j) {
          type ^= types.At(j);
          updated_types->SetAt(j, type);
        }
      }
    }
    if (updated_types != nullptr) {
      updated_types->SetAt(i, updated);
    }
  }
  if (updated_types == nullptr) {
    return ptr();
  }
  const auto& new_rt = RecordType::Handle(
      zone, RecordType::New(shape(), *updated_types, nullability(), space));
  new_rt.SetIsFinalized();
  return new_rt.ptr();
}

bool RecordType::IsSubtypeOf(
    const RecordType& other,
    Heap::Space space,
    FunctionTypeMapping* function_type_equivalence) const {
  if (ptr() == other.ptr()) {
    return true;
  }
  ASSERT(IsFinalized());
  ASSERT(other.IsFinalized());
  const intptr_t num_fields = NumFields();
  if (shape() != other.shape()) {
    // Different number of fields or different named fields.
    return false;
  }
  Thread* const thread = Thread::Current();
  if (!IsNullabilityEquivalent(thread, other, TypeEquality::kInSubtypeTest)) {
    return false;
  }
  // Check subtyping of record field types.
  Zone* const zone = thread->zone();
  AbstractType& field_type = Type::Handle(zone);
  AbstractType& other_field_type = Type::Handle(zone);
  for (intptr_t i = 0; i < num_fields; ++i) {
    field_type = FieldTypeAt(i);
    other_field_type = other.FieldTypeAt(i);
    if (!field_type.IsSubtypeOf(other_field_type, space,
                                function_type_equivalence)) {
      return false;
    }
  }
  return true;
}

RecordPtr Record::New(RecordShape shape, Heap::Space space) {
  const intptr_t num_fields = shape.num_fields();
  ASSERT(num_fields >= 0);
  auto raw = Object::Allocate<Record>(space, num_fields);
  NoSafepointScope no_safepoint;
  raw->untag()->set_shape(shape.AsSmi());
  return raw;
}

const char* Record::ToCString() const {
  if (IsNull()) {
    return "Record: null";
  }
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  ZoneTextBuffer printer(zone);
  const intptr_t num_fields = this->num_fields();
  const Array& field_names = Array::Handle(zone, GetFieldNames(thread));
  const intptr_t num_positional_fields = num_fields - field_names.Length();
  Object& obj = Object::Handle(zone);
  printer.AddString("Record (");
  for (intptr_t i = 0; i < num_fields; ++i) {
    if (i != 0) {
      printer.AddString(", ");
    }
    if (i >= num_positional_fields) {
      obj = field_names.At(i - num_positional_fields);
      printer.AddString(obj.ToCString());
      printer.AddString(": ");
    }
    obj = FieldAt(i);
    printer.AddString(obj.ToCString());
  }
  printer.AddString(")");
  return printer.buffer();
}

bool Record::CanonicalizeEquals(const Instance& other) const {
  if (this->ptr() == other.ptr()) {
    return true;
  }

  if (!other.IsRecord() || other.IsNull()) {
    return false;
  }

  const Record& other_rec = Record::Cast(other);
  if (shape() != other_rec.shape()) {
    return false;
  }

  const intptr_t num_fields = this->num_fields();
  for (intptr_t i = 0; i < num_fields; ++i) {
    if (this->FieldAt(i) != other_rec.FieldAt(i)) {
      return false;
    }
  }
  return true;
}

uint32_t Record::CanonicalizeHash() const {
  Thread* thread = Thread::Current();
  uint32_t hash = thread->heap()->GetCanonicalHash(ptr());
  if (hash != 0) {
    return hash;
  }
  hash = shape().AsInt();
  Instance& element = Instance::Handle();
  const intptr_t num_fields = this->num_fields();
  for (intptr_t i = 0; i < num_fields; ++i) {
    element ^= FieldAt(i);
    hash = CombineHashes(hash, element.CanonicalizeHash());
  }
  hash = FinalizeHash(hash, kHashBits);
  thread->heap()->SetCanonicalHash(ptr(), hash);
  return hash;
}

void Record::CanonicalizeFieldsLocked(Thread* thread) const {
  Zone* zone = thread->zone();
  Instance& obj = Instance::Handle(zone);
  const intptr_t num_fields = this->num_fields();
  for (intptr_t i = 0; i < num_fields; ++i) {
    obj ^= FieldAt(i);
    obj = obj.CanonicalizeLocked(thread);
    SetFieldAt(i, obj);
  }
}

RecordTypePtr Record::GetRecordType(TypeVisibility visibility) const {
  Zone* const zone = Thread::Current()->zone();
  const intptr_t num_fields = this->num_fields();
  const Array& field_types =
      Array::Handle(zone, Array::New(num_fields, Heap::kOld));
  Instance& obj = Instance::Handle(zone);
  AbstractType& type = AbstractType::Handle(zone);
  for (intptr_t i = 0; i < num_fields; ++i) {
    obj ^= FieldAt(i);
    type = obj.GetType(Heap::kNew, visibility);
    field_types.SetAt(i, type);
  }
  type = RecordType::New(shape(), field_types, Nullability::kNonNullable);
  type = ClassFinalizer::FinalizeType(type);
  return RecordType::Cast(type).ptr();
}

intptr_t Record::GetPositionalFieldIndexFromFieldName(
    const String& field_name) {
  if (field_name.IsOneByteString() && field_name.Length() >= 1 &&
      field_name.CharAt(0) == '$') {
    int64_t value = 0;
    const char* cstr = field_name.ToCString();
    if (OS::StringToInt64(cstr + 1 /* skip '$' */, &value)) {
      if (value >= 1 && value < kMaxElements) {
        return static_cast<intptr_t>(value - 1);
      }
    }
  }
  return -1;
}

intptr_t Record::GetFieldIndexByName(Thread* thread,
                                     const String& field_name) const {
  ASSERT(field_name.IsSymbol());
  const intptr_t field_index =
      Record::GetPositionalFieldIndexFromFieldName(field_name);
  const Array& field_names = Array::Handle(GetFieldNames(thread));
  const intptr_t num_positional_fields = num_fields() - field_names.Length();
  if ((field_index >= 0) && (field_index < num_positional_fields)) {
    return field_index;
  } else {
    for (intptr_t i = 0, n = field_names.Length(); i < n; ++i) {
      if (field_names.At(i) == field_name.ptr()) {
        return num_positional_fields + i;
      }
    }
  }
  return -1;
}

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

  static bool IsMatch(const Object& a, const Object& b) {
    return Array::Cast(a).CanonicalizeEquals(Array::Cast(b));
  }

  static uword Hash(const Object& key) {
    return Array::Cast(key).CanonicalizeHash();
  }

  static ObjectPtr NewKey(const Array& arr) { return arr.ptr(); }
};
typedef UnorderedHashMap<RecordFieldNamesMapTraits> RecordFieldNamesMap;

RecordShape RecordShape::Register(Thread* thread,
                                  intptr_t num_fields,
                                  const Array& field_names) {
  ASSERT(!field_names.IsNull());
  ASSERT(field_names.IsImmutable());
  ASSERT(field_names.ptr() == Object::empty_array().ptr() ||
         field_names.Length() > 0);

  Zone* zone = thread->zone();
  IsolateGroup* isolate_group = thread->isolate_group();
  ObjectStore* object_store = isolate_group->object_store();

  if (object_store->record_field_names<std::memory_order_acquire>() ==
      Array::null()) {
    // First-time initialization.
    SafepointWriteRwLocker ml(thread, isolate_group->program_lock());
    if (object_store->record_field_names() == Array::null()) {
      // Reserve record field names index 0 for records without named fields.
      RecordFieldNamesMap map(
          HashTables::New<RecordFieldNamesMap>(16, Heap::kOld));
      map.InsertOrGetValue(Object::empty_array(),
                           Smi::Handle(zone, Smi::New(0)));
      ASSERT(map.NumOccupied() == 1);
      object_store->set_record_field_names_map(map.Release());
      const auto& table = Array::Handle(zone, Array::New(16));
      table.SetAt(0, Object::empty_array());
      object_store->set_record_field_names<std::memory_order_release>(table);
    }
  }

#if defined(DART_PRECOMPILER)
  const intptr_t kMaxNumFields = compiler::target::RecordShape::kMaxNumFields;
  const intptr_t kMaxFieldNamesIndex =
      compiler::target::RecordShape::kMaxFieldNamesIndex;
#else
  const intptr_t kMaxNumFields = RecordShape::kMaxNumFields;
  const intptr_t kMaxFieldNamesIndex = RecordShape::kMaxFieldNamesIndex;
#endif

  if (num_fields > kMaxNumFields) {
    FATAL("Too many record fields");
  }
  if (field_names.ptr() == Object::empty_array().ptr()) {
    return RecordShape::ForUnnamed(num_fields);
  }

  {
    SafepointReadRwLocker ml(thread, isolate_group->program_lock());
    RecordFieldNamesMap map(object_store->record_field_names_map());
    Smi& index = Smi::Handle(zone);
    index ^= map.GetOrNull(field_names);
    ASSERT(map.Release().ptr() == object_store->record_field_names_map());
    if (!index.IsNull()) {
      return RecordShape(num_fields, index.Value());
    }
  }

  SafepointWriteRwLocker ml(thread, isolate_group->program_lock());
  RecordFieldNamesMap map(object_store->record_field_names_map());
  const intptr_t new_index = map.NumOccupied();
  if (new_index > kMaxFieldNamesIndex) {
    FATAL("Too many record shapes");
  }

  const intptr_t index = Smi::Value(Smi::RawCast(map.InsertOrGetValue(
      field_names, Smi::Handle(zone, Smi::New(new_index)))));
  ASSERT(index > 0);

  if (index == new_index) {
    ASSERT(map.NumOccupied() == (new_index + 1));
    Array& table = Array::Handle(zone, object_store->record_field_names());
    intptr_t capacity = table.Length();
    if (index >= table.Length()) {
      capacity = capacity + (capacity >> 2);
      table = Array::Grow(table, capacity);
      object_store->set_record_field_names(table);
    }
    table.SetAt(index, field_names);
  } else {
    ASSERT(index < new_index);
  }
  object_store->set_record_field_names_map(map.Release());

  const RecordShape shape(num_fields, index);
  ASSERT(shape.GetFieldNames(thread) == field_names.ptr());
  ASSERT(shape.num_fields() == num_fields);
  return shape;
}

ArrayPtr RecordShape::GetFieldNames(Thread* thread) const {
  ObjectStore* object_store = thread->isolate_group()->object_store();
  Array& table =
      Array::Handle(thread->zone(), object_store->record_field_names());
  ASSERT(!table.IsNull());
  return Array::RawCast(table.At(field_names_index()));
}

}  // namespace dart
