// 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.

#ifndef RUNTIME_VM_OBJECT_H_
#define RUNTIME_VM_OBJECT_H_

#if defined(SHOULD_NOT_INCLUDE_RUNTIME)
#error "Should not include runtime"
#endif

#include <limits>
#include <tuple>

#include "include/dart_api.h"
#include "platform/assert.h"
#include "platform/atomic.h"
#include "platform/thread_sanitizer.h"
#include "platform/utils.h"
#include "vm/bitmap.h"
#include "vm/code_comments.h"
#include "vm/code_entry_kind.h"
#include "vm/compiler/assembler/object_pool_builder.h"
#include "vm/compiler/method_recognizer.h"
#include "vm/compiler/runtime_api.h"
#include "vm/dart.h"
#include "vm/flags.h"
#include "vm/globals.h"
#include "vm/growable_array.h"
#include "vm/handles.h"
#include "vm/heap/heap.h"
#include "vm/isolate.h"
#include "vm/json_stream.h"
#include "vm/os.h"
#include "vm/raw_object.h"
#include "vm/report.h"
#include "vm/static_type_exactness_state.h"
#include "vm/thread.h"
#include "vm/token_position.h"

namespace dart {

// Forward declarations.
namespace compiler {
class Assembler;
}

namespace kernel {
class Program;
class TreeNode;
}  // namespace kernel

#define DEFINE_FORWARD_DECLARATION(clazz) class clazz;
CLASS_LIST(DEFINE_FORWARD_DECLARATION)
#undef DEFINE_FORWARD_DECLARATION
class Api;
class ArgumentsDescriptor;
class Closure;
class Code;
class DeoptInstr;
class DisassemblyFormatter;
class FinalizablePersistentHandle;
class FlowGraphCompiler;
class HierarchyInfo;
class LocalScope;
class CallSiteResetter;
class CodeStatistics;
class IsolateGroupReloadContext;
class ObjectGraphCopier;
class NativeArguments;

#define REUSABLE_FORWARD_DECLARATION(name) class Reusable##name##HandleScope;
REUSABLE_HANDLE_LIST(REUSABLE_FORWARD_DECLARATION)
#undef REUSABLE_FORWARD_DECLARATION

class Symbols;
class BaseTextBuffer;

#if defined(DEBUG)
#define CHECK_HANDLE() CheckHandle();
#else
#define CHECK_HANDLE()
#endif

// For AllStatic classes like OneByteString. Checks that
// ContainsCompressedPointers() returns the same value for AllStatic class and
// class used for handles.
#define ALLSTATIC_CONTAINS_COMPRESSED_IMPLEMENTATION(object, handle)           \
  static_assert(std::is_base_of<dart::handle##Ptr, dart::object##Ptr>::value,  \
                #object "Ptr must be a subtype of " #handle "Ptr");            \
  static_assert(dart::handle::ContainsCompressedPointers() ==                  \
                    dart::Untagged##object::kContainsCompressedPointers,       \
                "Pointer compression in Untagged" #object                      \
                " must match pointer compression in Untagged" #handle);        \
  static constexpr bool ContainsCompressedPointers() {                         \
    return dart::Untagged##object::kContainsCompressedPointers;                \
  }

#define BASE_OBJECT_IMPLEMENTATION(object, super)                              \
 public: /* NOLINT */                                                          \
  using UntaggedObjectType = dart::Untagged##object;                           \
  using ObjectPtrType = dart::object##Ptr;                                     \
  static_assert(!dart::super::ContainsCompressedPointers() ||                  \
                    UntaggedObjectType::kContainsCompressedPointers,           \
                "Untagged" #object                                             \
                " must have compressed pointers, as supertype Untagged" #super \
                " has compressed pointers");                                   \
  static constexpr bool ContainsCompressedPointers() {                         \
    return UntaggedObjectType::kContainsCompressedPointers;                    \
  }                                                                            \
  object##Ptr ptr() const { return static_cast<object##Ptr>(ptr_); }           \
  bool Is##object() const { return true; }                                     \
  DART_NOINLINE static object& Handle() {                                      \
    return static_cast<object&>(                                               \
        HandleImpl(Thread::Current()->zone(), object::null(), kClassId));      \
  }                                                                            \
  DART_NOINLINE static object& Handle(Zone* zone) {                            \
    return static_cast<object&>(HandleImpl(zone, object::null(), kClassId));   \
  }                                                                            \
  DART_NOINLINE static object& Handle(object##Ptr ptr) {                       \
    return static_cast<object&>(                                               \
        HandleImpl(Thread::Current()->zone(), ptr, kClassId));                 \
  }                                                                            \
  DART_NOINLINE static object& Handle(Zone* zone, object##Ptr ptr) {           \
    return static_cast<object&>(HandleImpl(zone, ptr, kClassId));              \
  }                                                                            \
  DART_NOINLINE static object& ZoneHandle() {                                  \
    return static_cast<object&>(                                               \
        ZoneHandleImpl(Thread::Current()->zone(), object::null(), kClassId));  \
  }                                                                            \
  DART_NOINLINE static object& ZoneHandle(Zone* zone) {                        \
    return static_cast<object&>(                                               \
        ZoneHandleImpl(zone, object::null(), kClassId));                       \
  }                                                                            \
  DART_NOINLINE static object& ZoneHandle(object##Ptr ptr) {                   \
    return static_cast<object&>(                                               \
        ZoneHandleImpl(Thread::Current()->zone(), ptr, kClassId));             \
  }                                                                            \
  DART_NOINLINE static object& ZoneHandle(Zone* zone, object##Ptr ptr) {       \
    return static_cast<object&>(ZoneHandleImpl(zone, ptr, kClassId));          \
  }                                                                            \
  static object* ReadOnlyHandle() {                                            \
    return static_cast<object*>(ReadOnlyHandleImpl(kClassId));                 \
  }                                                                            \
  DART_NOINLINE static object& CheckedHandle(Zone* zone, ObjectPtr ptr) {      \
    object* obj = reinterpret_cast<object*>(VMHandles::AllocateHandle(zone));  \
    initializeHandle(obj, ptr);                                                \
    if (!obj->Is##object()) {                                                  \
      FATAL2("Handle check failed: saw %s expected %s", obj->ToCString(),      \
             #object);                                                         \
    }                                                                          \
    return *obj;                                                               \
  }                                                                            \
  DART_NOINLINE static object& CheckedZoneHandle(Zone* zone, ObjectPtr ptr) {  \
    object* obj =                                                              \
        reinterpret_cast<object*>(VMHandles::AllocateZoneHandle(zone));        \
    initializeHandle(obj, ptr);                                                \
    if (!obj->Is##object()) {                                                  \
      FATAL2("Handle check failed: saw %s expected %s", obj->ToCString(),      \
             #object);                                                         \
    }                                                                          \
    return *obj;                                                               \
  }                                                                            \
  DART_NOINLINE static object& CheckedZoneHandle(ObjectPtr ptr) {              \
    return CheckedZoneHandle(Thread::Current()->zone(), ptr);                  \
  }                                                                            \
  /* T::Cast cannot be applied to a null Object, because the object vtable */  \
  /* is not setup for type T, although some methods are supposed to work   */  \
  /* with null, for example Instance::Equals().                            */  \
  static const object& Cast(const Object& obj) {                               \
    ASSERT(obj.Is##object());                                                  \
    return reinterpret_cast<const object&>(obj);                               \
  }                                                                            \
  static object##Ptr RawCast(ObjectPtr raw) {                                  \
    ASSERT(Object::Handle(raw).IsNull() || Object::Handle(raw).Is##object());  \
    return static_cast<object##Ptr>(raw);                                      \
  }                                                                            \
  static object##Ptr null() {                                                  \
    return static_cast<object##Ptr>(Object::null());                           \
  }                                                                            \
  virtual const char* ToCString() const;                                       \
  static const ClassId kClassId = k##object##Cid;                              \
                                                                               \
 private: /* NOLINT */                                                         \
  /* Initialize the handle based on the ptr in the presence of null. */        \
  static void initializeHandle(object* obj, ObjectPtr ptr) {                   \
    obj->SetPtr(ptr, kClassId);                                                \
  }                                                                            \
  /* Disallow allocation, copy constructors and override super assignment. */  \
 public: /* NOLINT */                                                          \
  void operator delete(void* pointer) { UNREACHABLE(); }                       \
                                                                               \
 private: /* NOLINT */                                                         \
  void* operator new(size_t size);                                             \
  object(const object& value) = delete;                                        \
  void operator=(super##Ptr value) = delete;                                   \
  void operator=(const object& value) = delete;                                \
  void operator=(const super& value) = delete;

// Conditionally include object_service.cc functionality in the vtable to avoid
// link errors like the following:
//
// object.o:(.rodata._ZTVN4....E[_ZTVN4...E]+0x278):
// undefined reference to
// `dart::Instance::PrintSharedInstanceJSON(dart::JSONObject*, bool) const'.
//
#ifndef PRODUCT
#define OBJECT_SERVICE_SUPPORT(object)                                         \
 protected: /* NOLINT */                                                       \
  /* Object is printed as JSON into stream. If ref is true only a header */    \
  /* with an object id is printed. If ref is false the object is fully   */    \
  /* printed.                                                            */    \
  virtual void PrintJSONImpl(JSONStream* stream, bool ref) const;              \
  virtual const char* JSONType() const { return "" #object; }
#else
#define OBJECT_SERVICE_SUPPORT(object) protected: /* NOLINT */
#endif                                            // !PRODUCT

#define SNAPSHOT_SUPPORT(object)                                               \
  friend class object##MessageSerializationCluster;                            \
  friend class object##MessageDeserializationCluster;

#define OBJECT_IMPLEMENTATION(object, super)                                   \
 public: /* NOLINT */                                                          \
  DART_NOINLINE void operator=(object##Ptr value) {                            \
    initializeHandle(this, value);                                             \
  }                                                                            \
  DART_NOINLINE void operator^=(ObjectPtr value) {                             \
    initializeHandle(this, value);                                             \
    ASSERT(IsNull() || Is##object());                                          \
  }                                                                            \
                                                                               \
 protected: /* NOLINT */                                                       \
  object() : super() {}                                                        \
  BASE_OBJECT_IMPLEMENTATION(object, super)                                    \
  OBJECT_SERVICE_SUPPORT(object)                                               \
  friend class Object;

extern "C" void DFLRT_ExitSafepoint(NativeArguments __unusable_);

#define HEAP_OBJECT_IMPLEMENTATION(object, super)                              \
  OBJECT_IMPLEMENTATION(object, super);                                        \
  Untagged##object* untag() const {                                            \
    ASSERT(ptr() != null());                                                   \
    return const_cast<Untagged##object*>(ptr()->untag());                      \
  }                                                                            \
  SNAPSHOT_SUPPORT(object)                                                     \
  friend class StackFrame;                                                     \
  friend class Thread;                                                         \
  friend void DFLRT_ExitSafepoint(NativeArguments __unusable_);

// This macro is used to denote types that do not have a sub-type.
#define FINAL_HEAP_OBJECT_IMPLEMENTATION_HELPER(object, rettype, super)        \
 public: /* NOLINT */                                                          \
  void operator=(object##Ptr value) {                                          \
    ptr_ = value;                                                              \
    CHECK_HANDLE();                                                            \
  }                                                                            \
  void operator^=(ObjectPtr value) {                                           \
    ptr_ = value;                                                              \
    CHECK_HANDLE();                                                            \
  }                                                                            \
                                                                               \
 private: /* NOLINT */                                                         \
  object() : super() {}                                                        \
  BASE_OBJECT_IMPLEMENTATION(object, super)                                    \
  OBJECT_SERVICE_SUPPORT(object)                                               \
  Untagged##object* untag() const {                                            \
    ASSERT(ptr() != null());                                                   \
    return const_cast<Untagged##object*>(ptr()->untag());                      \
  }                                                                            \
  static intptr_t NextFieldOffset() { return -kWordSize; }                     \
  SNAPSHOT_SUPPORT(rettype)                                                    \
  friend class Object;                                                         \
  friend class StackFrame;                                                     \
  friend class Thread;                                                         \
  friend void DFLRT_ExitSafepoint(NativeArguments __unusable_);

#define FINAL_HEAP_OBJECT_IMPLEMENTATION(object, super)                        \
  FINAL_HEAP_OBJECT_IMPLEMENTATION_HELPER(object, object, super)

#define MINT_OBJECT_IMPLEMENTATION(object, rettype, super)                     \
  FINAL_HEAP_OBJECT_IMPLEMENTATION_HELPER(object, rettype, super)

// In precompiled runtime, there is no access to runtime_api.cc since host
// and target are the same. In those cases, the namespace dart is used to refer
// to the target namespace
#if defined(DART_PRECOMPILED_RUNTIME)
namespace RTN = dart;
#else
namespace RTN = dart::compiler::target;
#endif  //  defined(DART_PRECOMPILED_RUNTIME)

class Object {
 public:
  using UntaggedObjectType = UntaggedObject;
  using ObjectPtrType = ObjectPtr;

  // We use 30 bits for the hash code so hashes in a snapshot taken on a
  // 64-bit architecture stay in Smi range when loaded on a 32-bit
  // architecture.
  static const intptr_t kHashBits = 30;

  static ObjectPtr RawCast(ObjectPtr obj) { return obj; }

  virtual ~Object() {}

  static constexpr bool ContainsCompressedPointers() {
    return UntaggedObject::kContainsCompressedPointers;
  }
  ObjectPtr ptr() const { return ptr_; }
  void operator=(ObjectPtr value) { initializeHandle(this, value); }

  bool IsCanonical() const { return ptr()->untag()->IsCanonical(); }
  void SetCanonical() const { ptr()->untag()->SetCanonical(); }
  void ClearCanonical() const { ptr()->untag()->ClearCanonical(); }
  intptr_t GetClassId() const {
    return !ptr()->IsHeapObject() ? static_cast<intptr_t>(kSmiCid)
                                  : ptr()->untag()->GetClassId();
  }
  inline ClassPtr clazz() const;
  static intptr_t tags_offset() { return OFFSET_OF(UntaggedObject, tags_); }

// Class testers.
#define DEFINE_CLASS_TESTER(clazz)                                             \
  virtual bool Is##clazz() const { return false; }
  CLASS_LIST_FOR_HANDLES(DEFINE_CLASS_TESTER);
#undef DEFINE_CLASS_TESTER

  bool IsNull() const { return ptr_ == null_; }

  // Matches Object.toString on instances (except String::ToCString, bug 20583).
  virtual const char* ToCString() const {
    if (IsNull()) {
      return "null";
    } else {
      return "Object";
    }
  }

#ifndef PRODUCT
  void PrintJSON(JSONStream* stream, bool ref = true) const;
  virtual void PrintJSONImpl(JSONStream* stream, bool ref) const;
  virtual const char* JSONType() const { return IsNull() ? "null" : "Object"; }
#endif

  // Returns the name that is used to identify an object in the
  // namespace dictionary.
  // Object::DictionaryName() returns String::null(). Only subclasses
  // of Object that need to be entered in the library and library prefix
  // namespaces need to provide an implementation.
  virtual StringPtr DictionaryName() const;

  bool IsNew() const { return ptr()->IsNewObject(); }
  bool IsOld() const { return ptr()->IsOldObject(); }
#if defined(DEBUG)
  bool InVMIsolateHeap() const;
#else
  bool InVMIsolateHeap() const { return ptr()->untag()->InVMIsolateHeap(); }
#endif  // DEBUG

  // Print the object on stdout for debugging.
  void Print() const;

  bool IsZoneHandle() const {
    return VMHandles::IsZoneHandle(reinterpret_cast<uword>(this));
  }

  bool IsReadOnlyHandle() const;

  bool IsNotTemporaryScopedHandle() const;

  static Object& Handle(Zone* zone, ObjectPtr ptr) {
    Object* obj = reinterpret_cast<Object*>(VMHandles::AllocateHandle(zone));
    initializeHandle(obj, ptr);
    return *obj;
  }
  static Object* ReadOnlyHandle() {
    Object* obj = reinterpret_cast<Object*>(Dart::AllocateReadOnlyHandle());
    initializeHandle(obj, Object::null());
    return obj;
  }

  static Object& Handle() { return Handle(Thread::Current()->zone(), null_); }

  static Object& Handle(Zone* zone) { return Handle(zone, null_); }

  static Object& Handle(ObjectPtr ptr) {
    return Handle(Thread::Current()->zone(), ptr);
  }

  static Object& ZoneHandle(Zone* zone, ObjectPtr ptr) {
    Object* obj =
        reinterpret_cast<Object*>(VMHandles::AllocateZoneHandle(zone));
    initializeHandle(obj, ptr);
    return *obj;
  }

  static Object& ZoneHandle(Zone* zone) { return ZoneHandle(zone, null_); }

  static Object& ZoneHandle() {
    return ZoneHandle(Thread::Current()->zone(), null_);
  }

  static Object& ZoneHandle(ObjectPtr ptr) {
    return ZoneHandle(Thread::Current()->zone(), ptr);
  }

  static ObjectPtr null() { return null_; }

#if defined(HASH_IN_OBJECT_HEADER)
  static uint32_t GetCachedHash(const ObjectPtr obj) {
    return obj->untag()->GetHeaderHash();
  }

  static uint32_t SetCachedHashIfNotSet(ObjectPtr obj, uint32_t hash) {
    return obj->untag()->SetHeaderHashIfNotSet(hash);
  }
#endif

  // The list below enumerates read-only handles for singleton
  // objects that are shared between the different isolates.
  //
  // - sentinel is a value that cannot be produced by Dart code. It can be used
  // to mark special values, for example to distinguish "uninitialized" fields.
  // - transition_sentinel is a value marking that we are transitioning from
  // sentinel, e.g., computing a field value. Used to detect circular
  // initialization.
  // - unknown_constant and non_constant are optimizing compiler's constant
  // propagation constants.
#define SHARED_READONLY_HANDLES_LIST(V)                                        \
  V(Object, null_object)                                                       \
  V(Class, null_class)                                                         \
  V(Array, null_array)                                                         \
  V(String, null_string)                                                       \
  V(Instance, null_instance)                                                   \
  V(Function, null_function)                                                   \
  V(FunctionType, null_function_type)                                          \
  V(TypeArguments, null_type_arguments)                                        \
  V(CompressedStackMaps, null_compressed_stackmaps)                            \
  V(TypeArguments, empty_type_arguments)                                       \
  V(Array, empty_array)                                                        \
  V(Array, zero_array)                                                         \
  V(ContextScope, empty_context_scope)                                         \
  V(ObjectPool, empty_object_pool)                                             \
  V(CompressedStackMaps, empty_compressed_stackmaps)                           \
  V(PcDescriptors, empty_descriptors)                                          \
  V(LocalVarDescriptors, empty_var_descriptors)                                \
  V(ExceptionHandlers, empty_exception_handlers)                               \
  V(Array, extractor_parameter_types)                                          \
  V(Array, extractor_parameter_names)                                          \
  V(Sentinel, sentinel)                                                        \
  V(Sentinel, transition_sentinel)                                             \
  V(Sentinel, unknown_constant)                                                \
  V(Sentinel, non_constant)                                                    \
  V(Bool, bool_true)                                                           \
  V(Bool, bool_false)                                                          \
  V(Smi, smi_illegal_cid)                                                      \
  V(Smi, smi_zero)                                                             \
  V(ApiError, no_callbacks_error)                                              \
  V(UnwindError, unwind_in_progress_error)                                     \
  V(LanguageError, snapshot_writer_error)                                      \
  V(LanguageError, branch_offset_error)                                        \
  V(LanguageError, speculative_inlining_error)                                 \
  V(LanguageError, background_compilation_error)                               \
  V(LanguageError, out_of_memory_error)                                        \
  V(Array, vm_isolate_snapshot_object_table)                                   \
  V(Type, dynamic_type)                                                        \
  V(Type, void_type)                                                           \
  V(AbstractType, null_abstract_type)

#define DEFINE_SHARED_READONLY_HANDLE_GETTER(Type, name)                       \
  static const Type& name() {                                                  \
    ASSERT(name##_ != nullptr);                                                \
    return *name##_;                                                           \
  }
  SHARED_READONLY_HANDLES_LIST(DEFINE_SHARED_READONLY_HANDLE_GETTER)
#undef DEFINE_SHARED_READONLY_HANDLE_GETTER

  static void set_vm_isolate_snapshot_object_table(const Array& table);

  static ClassPtr class_class() { return class_class_; }
  static ClassPtr dynamic_class() { return dynamic_class_; }
  static ClassPtr void_class() { return void_class_; }
  static ClassPtr type_parameters_class() { return type_parameters_class_; }
  static ClassPtr type_arguments_class() { return type_arguments_class_; }
  static ClassPtr patch_class_class() { return patch_class_class_; }
  static ClassPtr function_class() { return function_class_; }
  static ClassPtr closure_data_class() { return closure_data_class_; }
  static ClassPtr ffi_trampoline_data_class() {
    return ffi_trampoline_data_class_;
  }
  static ClassPtr field_class() { return field_class_; }
  static ClassPtr script_class() { return script_class_; }
  static ClassPtr library_class() { return library_class_; }
  static ClassPtr namespace_class() { return namespace_class_; }
  static ClassPtr kernel_program_info_class() {
    return kernel_program_info_class_;
  }
  static ClassPtr code_class() { return code_class_; }
  static ClassPtr instructions_class() { return instructions_class_; }
  static ClassPtr instructions_section_class() {
    return instructions_section_class_;
  }
  static ClassPtr instructions_table_class() {
    return instructions_table_class_;
  }
  static ClassPtr object_pool_class() { return object_pool_class_; }
  static ClassPtr pc_descriptors_class() { return pc_descriptors_class_; }
  static ClassPtr code_source_map_class() { return code_source_map_class_; }
  static ClassPtr compressed_stackmaps_class() {
    return compressed_stackmaps_class_;
  }
  static ClassPtr var_descriptors_class() { return var_descriptors_class_; }
  static ClassPtr exception_handlers_class() {
    return exception_handlers_class_;
  }
  static ClassPtr deopt_info_class() { return deopt_info_class_; }
  static ClassPtr context_class() { return context_class_; }
  static ClassPtr context_scope_class() { return context_scope_class_; }
  static ClassPtr sentinel_class() { return sentinel_class_; }
  static ClassPtr api_error_class() { return api_error_class_; }
  static ClassPtr language_error_class() { return language_error_class_; }
  static ClassPtr unhandled_exception_class() {
    return unhandled_exception_class_;
  }
  static ClassPtr unwind_error_class() { return unwind_error_class_; }
  static ClassPtr singletargetcache_class() { return singletargetcache_class_; }
  static ClassPtr unlinkedcall_class() { return unlinkedcall_class_; }
  static ClassPtr monomorphicsmiablecall_class() {
    return monomorphicsmiablecall_class_;
  }
  static ClassPtr icdata_class() { return icdata_class_; }
  static ClassPtr megamorphic_cache_class() { return megamorphic_cache_class_; }
  static ClassPtr subtypetestcache_class() { return subtypetestcache_class_; }
  static ClassPtr loadingunit_class() { return loadingunit_class_; }
  static ClassPtr weak_serialization_reference_class() {
    return weak_serialization_reference_class_;
  }

  // Initialize the VM isolate.
  static void InitNullAndBool(IsolateGroup* isolate_group);
  static void Init(IsolateGroup* isolate_group);
  static void InitVtables();
  static void FinishInit(IsolateGroup* isolate_group);
  static void FinalizeVMIsolate(IsolateGroup* isolate_group);
  static void FinalizeReadOnlyObject(ObjectPtr object);

  static void Cleanup();

  // Initialize a new isolate either from a Kernel IR, from source, or from a
  // snapshot.
  static ErrorPtr Init(IsolateGroup* isolate_group,
                       const uint8_t* kernel_buffer,
                       intptr_t kernel_buffer_size);

  static void MakeUnusedSpaceTraversable(const Object& obj,
                                         intptr_t original_size,
                                         intptr_t used_size);

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedObject));
  }

  template <class FakeObject>
  static void VerifyBuiltinVtable(intptr_t cid) {
    FakeObject fake;
    if (cid >= kNumPredefinedCids) {
      cid = kInstanceCid;
    }
    ASSERT(builtin_vtables_[cid] == fake.vtable());
  }
  static void VerifyBuiltinVtables();

  static const ClassId kClassId = kObjectCid;

  // Different kinds of name visibility.
  enum NameVisibility {
    // Internal names are the true names of classes, fields,
    // etc. inside the vm.  These names include privacy suffixes,
    // getter prefixes, and trailing dots on unnamed constructors.
    //
    // The names of core implementation classes (like _OneByteString)
    // are preserved as well.
    //
    // e.g.
    //   private getter             -> get:foo@6be832b
    //   private constructor        -> _MyClass@6b3832b.
    //   private named constructor  -> _MyClass@6b3832b.named
    //   core impl class name shown -> _OneByteString
    kInternalName = 0,

    // Scrubbed names drop privacy suffixes, getter prefixes, and
    // trailing dots on unnamed constructors.  These names are used in
    // the vm service.
    //
    // e.g.
    //   get:foo@6be832b        -> foo
    //   _MyClass@6b3832b.      -> _MyClass
    //   _MyClass@6b3832b.named -> _MyClass.named
    //   _OneByteString         -> _OneByteString (not remapped)
    kScrubbedName,

    // User visible names are appropriate for reporting type errors
    // directly to programmers.  The names have been scrubbed and
    // the names of core implementation classes are remapped to their
    // public interface names.
    //
    // e.g.
    //   get:foo@6be832b        -> foo
    //   _MyClass@6b3832b.      -> _MyClass
    //   _MyClass@6b3832b.named -> _MyClass.named
    //   _OneByteString         -> String (remapped)
    kUserVisibleName
  };

  // Sometimes simple formating might produce the same name for two different
  // entities, for example we might inject a synthetic forwarder into the
  // class which has the same name as an already existing function, or
  // two different types can be formatted as X<T> because T has different
  // meaning (refers to a different type parameter) in these two types.
  // Such ambiguity might be acceptable in some contexts but not in others, so
  // some formatting methods have two modes - one which tries to be more
  // user friendly, and another one which tries to avoid name conflicts by
  // emitting longer and less user friendly names.
  enum class NameDisambiguation {
    kYes,
    kNo,
  };

 protected:
  friend ObjectPtr AllocateObject(intptr_t, intptr_t);

  // Used for extracting the C++ vtable during bringup.
  Object() : ptr_(null_) {}

  uword raw_value() const { return static_cast<uword>(ptr()); }

  inline void SetPtr(ObjectPtr value, intptr_t default_cid);
  void CheckHandle() const;
  DART_NOINLINE static Object& HandleImpl(Zone* zone,
                                          ObjectPtr ptr,
                                          intptr_t default_cid) {
    Object* obj = reinterpret_cast<Object*>(VMHandles::AllocateHandle(zone));
    obj->SetPtr(ptr, default_cid);
    return *obj;
  }
  DART_NOINLINE static Object& ZoneHandleImpl(Zone* zone,
                                              ObjectPtr ptr,
                                              intptr_t default_cid) {
    Object* obj =
        reinterpret_cast<Object*>(VMHandles::AllocateZoneHandle(zone));
    obj->SetPtr(ptr, default_cid);
    return *obj;
  }
  DART_NOINLINE static Object* ReadOnlyHandleImpl(intptr_t cid) {
    Object* obj = reinterpret_cast<Object*>(Dart::AllocateReadOnlyHandle());
    obj->SetPtr(Object::null(), cid);
    return obj;
  }

  // Memcpy to account for the strict aliasing rule.
  // Explicit cast to silence -Wdynamic-class-memaccess.
  // This is still undefined behavior because we're messing with the internal
  // representation of C++ objects, but works okay in practice with
  // -fno-strict-vtable-pointers.
  cpp_vtable vtable() const {
    cpp_vtable result;
    memcpy(&result, reinterpret_cast<const void*>(this),  // NOLINT
           sizeof(result));
    return result;
  }
  void set_vtable(cpp_vtable value) {
    memcpy(reinterpret_cast<void*>(this), &value,  // NOLINT
           sizeof(cpp_vtable));
  }

  static ObjectPtr Allocate(intptr_t cls_id,
                            intptr_t size,
                            Heap::Space space,
                            bool compressed);

  static constexpr intptr_t RoundedAllocationSize(intptr_t size) {
    return Utils::RoundUp(size, kObjectAlignment);
  }

  bool Contains(uword addr) const { return ptr()->untag()->Contains(addr); }

  // Start of field mutator guards.
  //
  // All writes to heap objects should ultimately pass through one of the
  // methods below or their counterparts in RawObject, to ensure that the
  // write barrier is correctly applied.

  template <typename type, std::memory_order order = std::memory_order_relaxed>
  type LoadPointer(type const* addr) const {
    return ptr()->untag()->LoadPointer<type, order>(addr);
  }

  template <typename type, std::memory_order order = std::memory_order_relaxed>
  void StorePointer(type const* addr, type value) const {
    ptr()->untag()->StorePointer<type, order>(addr, value);
  }
  template <typename type,
            typename compressed_type,
            std::memory_order order = std::memory_order_relaxed>
  void StoreCompressedPointer(compressed_type const* addr, type value) const {
    ptr()->untag()->StoreCompressedPointer<type, compressed_type, order>(addr,
                                                                         value);
  }

  // Use for storing into an explicitly Smi-typed field of an object
  // (i.e., both the previous and new value are Smis).
  void StoreSmi(SmiPtr const* addr, SmiPtr value) const {
    ptr()->untag()->StoreSmi(addr, value);
  }

  template <typename FieldType>
  void StoreSimd128(const FieldType* addr, simd128_value_t value) const {
    ASSERT(Contains(reinterpret_cast<uword>(addr)));
    value.writeTo(const_cast<FieldType*>(addr));
  }

  template <typename FieldType>
  FieldType LoadNonPointer(const FieldType* addr) const {
    return *const_cast<FieldType*>(addr);
  }

  template <typename FieldType, std::memory_order order>
  FieldType LoadNonPointer(const FieldType* addr) const {
    return reinterpret_cast<std::atomic<FieldType>*>(
               const_cast<FieldType*>(addr))
        ->load(order);
  }

  // Needs two template arguments to allow assigning enums to fixed-size ints.
  template <typename FieldType, typename ValueType>
  void StoreNonPointer(const FieldType* addr, ValueType value) const {
    // Can't use Contains, as it uses tags_, which is set through this method.
    ASSERT(reinterpret_cast<uword>(addr) >= UntaggedObject::ToAddr(ptr()));
    *const_cast<FieldType*>(addr) = value;
  }

  template <typename FieldType, typename ValueType, std::memory_order order>
  void StoreNonPointer(const FieldType* addr, ValueType value) const {
    // Can't use Contains, as it uses tags_, which is set through this method.
    ASSERT(reinterpret_cast<uword>(addr) >= UntaggedObject::ToAddr(ptr()));
    reinterpret_cast<std::atomic<FieldType>*>(const_cast<FieldType*>(addr))
        ->store(value, order);
  }

  // Provides non-const access to non-pointer fields within the object. Such
  // access does not need a write barrier, but it is *not* GC-safe, since the
  // object might move, hence must be fully contained within a NoSafepointScope.
  template <typename FieldType>
  FieldType* UnsafeMutableNonPointer(const FieldType* addr) const {
    // Allow pointers at the end of variable-length data, and disallow pointers
    // within the header word.
    ASSERT(Contains(reinterpret_cast<uword>(addr) - 1) &&
           Contains(reinterpret_cast<uword>(addr) - kWordSize));
    // At least check that there is a NoSafepointScope and hope it's big enough.
    ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0);
    return const_cast<FieldType*>(addr);
  }

// Fail at link time if StoreNonPointer or UnsafeMutableNonPointer is
// instantiated with an object pointer type.
#define STORE_NON_POINTER_ILLEGAL_TYPE(type)                                   \
  template <typename ValueType>                                                \
  void StoreNonPointer(type##Ptr const* addr, ValueType value) const {         \
    UnimplementedMethod();                                                     \
  }                                                                            \
  type##Ptr* UnsafeMutableNonPointer(type##Ptr const* addr) const {            \
    UnimplementedMethod();                                                     \
    return NULL;                                                               \
  }

  CLASS_LIST(STORE_NON_POINTER_ILLEGAL_TYPE);
  void UnimplementedMethod() const;
#undef STORE_NON_POINTER_ILLEGAL_TYPE

  // Allocate an object and copy the body of 'orig'.
  static ObjectPtr Clone(const Object& orig,
                         Heap::Space space,
                         bool load_with_relaxed_atomics = false);

  // End of field mutator guards.

  ObjectPtr ptr_;  // The raw object reference.

 protected:
  void AddCommonObjectProperties(JSONObject* jsobj,
                                 const char* protocol_type,
                                 bool ref) const;

 private:
  static intptr_t NextFieldOffset() {
    // Indicates this class cannot be extended by dart code.
    return -kWordSize;
  }

  static void InitializeObject(uword address,
                               intptr_t id,
                               intptr_t size,
                               bool compressed);

  static void RegisterClass(const Class& cls,
                            const String& name,
                            const Library& lib);
  static void RegisterPrivateClass(const Class& cls,
                                   const String& name,
                                   const Library& lib);

  /* Initialize the handle based on the ptr in the presence of null. */
  static void initializeHandle(Object* obj, ObjectPtr ptr) {
    obj->SetPtr(ptr, kObjectCid);
  }

  static cpp_vtable builtin_vtables_[kNumPredefinedCids];

  // The static values below are singletons shared between the different
  // isolates. They are all allocated in the non-GC'd Dart::vm_isolate_.
  static ObjectPtr null_;
  static BoolPtr true_;
  static BoolPtr false_;

  static ClassPtr class_class_;            // Class of the Class vm object.
  static ClassPtr dynamic_class_;          // Class of the 'dynamic' type.
  static ClassPtr void_class_;             // Class of the 'void' type.
  static ClassPtr type_parameters_class_;  // Class of TypeParameters vm object.
  static ClassPtr type_arguments_class_;   // Class of TypeArguments vm object.
  static ClassPtr patch_class_class_;      // Class of the PatchClass vm object.
  static ClassPtr function_class_;         // Class of the Function vm object.
  static ClassPtr closure_data_class_;     // Class of ClosureData vm obj.
  static ClassPtr ffi_trampoline_data_class_;  // Class of FfiTrampolineData
                                               // vm obj.
  static ClassPtr field_class_;                // Class of the Field vm object.
  static ClassPtr script_class_;               // Class of the Script vm object.
  static ClassPtr library_class_;    // Class of the Library vm object.
  static ClassPtr namespace_class_;  // Class of Namespace vm object.
  static ClassPtr kernel_program_info_class_;  // Class of KernelProgramInfo vm
                                               // object.
  static ClassPtr code_class_;                 // Class of the Code vm object.

  static ClassPtr instructions_class_;  // Class of the Instructions vm object.
  static ClassPtr instructions_section_class_;  // Class of InstructionsSection.
  static ClassPtr instructions_table_class_;    // Class of InstructionsTable.
  static ClassPtr object_pool_class_;      // Class of the ObjectPool vm object.
  static ClassPtr pc_descriptors_class_;   // Class of PcDescriptors vm object.
  static ClassPtr code_source_map_class_;  // Class of CodeSourceMap vm object.
  static ClassPtr compressed_stackmaps_class_;  // Class of CompressedStackMaps.
  static ClassPtr var_descriptors_class_;       // Class of LocalVarDescriptors.
  static ClassPtr exception_handlers_class_;    // Class of ExceptionHandlers.
  static ClassPtr deopt_info_class_;            // Class of DeoptInfo.
  static ClassPtr context_class_;            // Class of the Context vm object.
  static ClassPtr context_scope_class_;      // Class of ContextScope vm object.
  static ClassPtr sentinel_class_;           // Class of Sentinel vm object.
  static ClassPtr singletargetcache_class_;  // Class of SingleTargetCache.
  static ClassPtr unlinkedcall_class_;       // Class of UnlinkedCall.
  static ClassPtr
      monomorphicsmiablecall_class_;         // Class of MonomorphicSmiableCall.
  static ClassPtr icdata_class_;             // Class of ICData.
  static ClassPtr megamorphic_cache_class_;  // Class of MegamorphiCache.
  static ClassPtr subtypetestcache_class_;   // Class of SubtypeTestCache.
  static ClassPtr loadingunit_class_;        // Class of LoadingUnit.
  static ClassPtr api_error_class_;          // Class of ApiError.
  static ClassPtr language_error_class_;     // Class of LanguageError.
  static ClassPtr unhandled_exception_class_;  // Class of UnhandledException.
  static ClassPtr unwind_error_class_;         // Class of UnwindError.
  // Class of WeakSerializationReference.
  static ClassPtr weak_serialization_reference_class_;

#define DECLARE_SHARED_READONLY_HANDLE(Type, name) static Type* name##_;
  SHARED_READONLY_HANDLES_LIST(DECLARE_SHARED_READONLY_HANDLE)
#undef DECLARE_SHARED_READONLY_HANDLE

  friend void ClassTable::Register(const Class& cls);
  friend void UntaggedObject::Validate(IsolateGroup* isolate_group) const;
  friend class Closure;
  friend class InstanceDeserializationCluster;
  friend class ObjectGraphCopier;  // For Object::InitializeObject
  friend class Simd128MessageDeserializationCluster;
  friend class OneByteString;
  friend class TwoByteString;
  friend class ExternalOneByteString;
  friend class ExternalTwoByteString;
  friend class Thread;

#define REUSABLE_FRIEND_DECLARATION(name)                                      \
  friend class Reusable##name##HandleScope;
  REUSABLE_HANDLE_LIST(REUSABLE_FRIEND_DECLARATION)
#undef REUSABLE_FRIEND_DECLARATION

  DISALLOW_ALLOCATION();
  DISALLOW_COPY_AND_ASSIGN(Object);
};

// Used to declare setters and getters for untagged object fields that are
// defined with the WSR_COMPRESSED_POINTER_FIELD macro.
//
// In the precompiler, the getter transparently unwraps the
// WeakSerializationReference, if present, to get the wrapped value of the
// appropriate type, since a WeakSerializationReference object should be
// transparent to the parts of the precompiler that are not the serializer.
// Meanwhile, the setter takes an Object to allow the precompiler to set the
// field to a WeakSerializationReference.
//
// Since WeakSerializationReferences are only used during precompilation,
// this macro creates the normally expected getter and setter otherwise.
#if defined(DART_PRECOMPILER)
#define PRECOMPILER_WSR_FIELD_DECLARATION(Type, Name)                          \
  Type##Ptr Name() const;                                                      \
  void set_##Name(const Object& value) const {                                 \
    untag()->set_##Name(value.ptr());                                          \
  }
#else
#define PRECOMPILER_WSR_FIELD_DECLARATION(Type, Name)                          \
  Type##Ptr Name() const { return untag()->Name(); }                           \
  void set_##Name(const Type& value) const;
#endif

class PassiveObject : public Object {
 public:
  void operator=(ObjectPtr value) { ptr_ = value; }
  void operator^=(ObjectPtr value) { ptr_ = value; }

  static PassiveObject& Handle(Zone* zone, ObjectPtr ptr) {
    PassiveObject* obj =
        reinterpret_cast<PassiveObject*>(VMHandles::AllocateHandle(zone));
    obj->ptr_ = ptr;
    obj->set_vtable(0);
    return *obj;
  }
  static PassiveObject& Handle(ObjectPtr ptr) {
    return Handle(Thread::Current()->zone(), ptr);
  }
  static PassiveObject& Handle() {
    return Handle(Thread::Current()->zone(), Object::null());
  }
  static PassiveObject& Handle(Zone* zone) {
    return Handle(zone, Object::null());
  }
  static PassiveObject& ZoneHandle(Zone* zone, ObjectPtr ptr) {
    PassiveObject* obj =
        reinterpret_cast<PassiveObject*>(VMHandles::AllocateZoneHandle(zone));
    obj->ptr_ = ptr;
    obj->set_vtable(0);
    return *obj;
  }
  static PassiveObject& ZoneHandle(ObjectPtr ptr) {
    return ZoneHandle(Thread::Current()->zone(), ptr);
  }
  static PassiveObject& ZoneHandle() {
    return ZoneHandle(Thread::Current()->zone(), Object::null());
  }
  static PassiveObject& ZoneHandle(Zone* zone) {
    return ZoneHandle(zone, Object::null());
  }

 private:
  PassiveObject() : Object() {}
  DISALLOW_ALLOCATION();
  DISALLOW_COPY_AND_ASSIGN(PassiveObject);
};

typedef ZoneGrowableHandlePtrArray<const AbstractType> Trail;
typedef ZoneGrowableHandlePtrArray<const AbstractType>* TrailPtr;

// A URIs array contains triplets of strings.
// The first string in the triplet is a type name (usually a class).
// The second string in the triplet is the URI of the type.
// The third string in the triplet is "print" if the triplet should be printed.
typedef ZoneGrowableHandlePtrArray<const String> URIs;

enum class Nullability : uint8_t {
  kNullable = 0,
  kNonNullable = 1,
  kLegacy = 2,
  // Adjust kNullabilityBitSize in app_snapshot.cc if adding new values.
};

// Equality kind between types.
enum class TypeEquality {
  kCanonical = 0,
  kSyntactical = 1,
  kInSubtypeTest = 2,
};

// The NNBDMode reflects the opted-in status of libraries.
// Note that the weak or strong checking mode is not reflected in NNBDMode.
enum class NNBDMode {
  // Status of the library:
  kLegacyLib = 0,   // Library is legacy.
  kOptedInLib = 1,  // Library is opted-in.
};

// The NNBDCompiledMode reflects the mode in which constants of the library were
// compiled by CFE.
enum class NNBDCompiledMode {
  kWeak = 0,
  kStrong = 1,
  kAgnostic = 2,
  kInvalid = 3,
};

class Class : public Object {
 public:
  enum InvocationDispatcherEntry {
    kInvocationDispatcherName,
    kInvocationDispatcherArgsDesc,
    kInvocationDispatcherFunction,
    kInvocationDispatcherEntrySize,
  };

  bool HasCompressedPointers() const;
  intptr_t host_instance_size() const {
    ASSERT(is_finalized() || is_prefinalized());
    return (untag()->host_instance_size_in_words_ * kCompressedWordSize);
  }
  intptr_t target_instance_size() const {
    ASSERT(is_finalized() || is_prefinalized());
#if defined(DART_PRECOMPILER)
    return (untag()->target_instance_size_in_words_ *
            compiler::target::kCompressedWordSize);
#else
    return host_instance_size();
#endif  // defined(DART_PRECOMPILER)
  }
  static intptr_t host_instance_size(ClassPtr clazz) {
    return (clazz->untag()->host_instance_size_in_words_ * kCompressedWordSize);
  }
  static intptr_t target_instance_size(ClassPtr clazz) {
#if defined(DART_PRECOMPILER)
    return (clazz->untag()->target_instance_size_in_words_ *
            compiler::target::kCompressedWordSize);
#else
    return host_instance_size(clazz);
#endif  // defined(DART_PRECOMPILER)
  }
  void set_instance_size(intptr_t host_value_in_bytes,
                         intptr_t target_value_in_bytes) const {
    ASSERT(kCompressedWordSize != 0);
    set_instance_size_in_words(
        host_value_in_bytes / kCompressedWordSize,
        target_value_in_bytes / compiler::target::kCompressedWordSize);
  }
  void set_instance_size_in_words(intptr_t host_value,
                                  intptr_t target_value) const {
    ASSERT(
        Utils::IsAligned((host_value * kCompressedWordSize), kObjectAlignment));
    StoreNonPointer(&untag()->host_instance_size_in_words_, host_value);
#if defined(DART_PRECOMPILER)
    ASSERT(
        Utils::IsAligned((target_value * compiler::target::kCompressedWordSize),
                         compiler::target::kObjectAlignment));
    StoreNonPointer(&untag()->target_instance_size_in_words_, target_value);
#else
    // Could be different only during cross-compilation.
    ASSERT_EQUAL(host_value, target_value);
#endif  // defined(DART_PRECOMPILER)
  }

  intptr_t host_next_field_offset() const {
    return untag()->host_next_field_offset_in_words_ * kCompressedWordSize;
  }
  intptr_t target_next_field_offset() const {
#if defined(DART_PRECOMPILER)
    return untag()->target_next_field_offset_in_words_ *
           compiler::target::kCompressedWordSize;
#else
    return host_next_field_offset();
#endif  // defined(DART_PRECOMPILER)
  }
  void set_next_field_offset(intptr_t host_value_in_bytes,
                             intptr_t target_value_in_bytes) const {
    set_next_field_offset_in_words(
        host_value_in_bytes / kCompressedWordSize,
        target_value_in_bytes / compiler::target::kCompressedWordSize);
  }
  void set_next_field_offset_in_words(intptr_t host_value,
                                      intptr_t target_value) const {
    // Assert that the next field offset is either negative (ie, this object
    // can't be extended by dart code), or rounds up to the kObjectAligned
    // instance size.
    ASSERT((host_value < 0) ||
           ((host_value <= untag()->host_instance_size_in_words_) &&
            (host_value + (kObjectAlignment / kCompressedWordSize) >
             untag()->host_instance_size_in_words_)));
    StoreNonPointer(&untag()->host_next_field_offset_in_words_, host_value);
#if defined(DART_PRECOMPILER)
    ASSERT((target_value < 0) ||
           ((target_value <= untag()->target_instance_size_in_words_) &&
            (target_value + (compiler::target::kObjectAlignment /
                             compiler::target::kCompressedWordSize) >
             untag()->target_instance_size_in_words_)));
    StoreNonPointer(&untag()->target_next_field_offset_in_words_, target_value);
#else
    // Could be different only during cross-compilation.
    ASSERT_EQUAL(host_value, target_value);
#endif  // defined(DART_PRECOMPILER)
  }

  static bool is_valid_id(intptr_t value) {
    return UntaggedObject::ClassIdTag::is_valid(value);
  }
  intptr_t id() const { return untag()->id_; }
  void set_id(intptr_t value) const {
    ASSERT(value >= 0 && value < std::numeric_limits<classid_t>::max());
    StoreNonPointer(&untag()->id_, value);
  }
  static intptr_t id_offset() { return OFFSET_OF(UntaggedClass, id_); }
  static intptr_t num_type_arguments_offset() {
    return OFFSET_OF(UntaggedClass, num_type_arguments_);
  }

  StringPtr Name() const;
  StringPtr ScrubbedName() const;
  const char* ScrubbedNameCString() const;
  StringPtr UserVisibleName() const;
  const char* UserVisibleNameCString() const;

  const char* NameCString(NameVisibility name_visibility) const;

  // The mixin for this class if one exists. Otherwise, returns a raw pointer
  // to this class.
  ClassPtr Mixin() const;

  // The NNBD mode of the library declaring this class.
  NNBDMode nnbd_mode() const;

  bool IsInFullSnapshot() const;

  virtual StringPtr DictionaryName() const { return Name(); }

  ScriptPtr script() const { return untag()->script(); }
  void set_script(const Script& value) const;

  TokenPosition token_pos() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    return TokenPosition::kNoSource;
#else
    return untag()->token_pos_;
#endif  // defined(DART_PRECOMPILED_RUNTIME)
  }

#if !defined(DART_PRECOMPILED_RUNTIME)
  void set_token_pos(TokenPosition value) const;
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

  TokenPosition end_token_pos() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    return TokenPosition::kNoSource;
#else
    return untag()->end_token_pos_;
#endif  // defined(DART_PRECOMPILED_RUNTIME)
  }

#if !defined(DART_PRECOMPILED_RUNTIME)
  void set_end_token_pos(TokenPosition value) const;
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

  int32_t SourceFingerprint() const;

  // Return the Type with type parameters declared by this class filled in with
  // dynamic and type parameters declared in superclasses filled in as declared
  // in superclass clauses.
  AbstractTypePtr RareType() const;

  // Return the Type whose arguments are the type parameters declared by this
  // class preceded by the type arguments declared for superclasses, etc.
  // e.g. given
  // class B<T, S>
  // class C<R> extends B<R, int>
  // C.DeclarationType() --> C [R, int, R]
  // The declaration type's nullability is either legacy or non-nullable when
  // the non-nullable experiment is enabled.
  TypePtr DeclarationType() const;

  static intptr_t declaration_type_offset() {
    return OFFSET_OF(UntaggedClass, declaration_type_);
  }

  LibraryPtr library() const { return untag()->library(); }
  void set_library(const Library& value) const;

  // The formal type parameters and their bounds (no defaults), are specified as
  // an object of type TypeParameters.
  TypeParametersPtr type_parameters() const {
    ASSERT(is_declaration_loaded());
    return untag()->type_parameters();
  }
  void set_type_parameters(const TypeParameters& value) const;
  intptr_t NumTypeParameters(Thread* thread) const;
  intptr_t NumTypeParameters() const {
    return NumTypeParameters(Thread::Current());
  }

  // Return the type parameter declared at index.
  TypeParameterPtr TypeParameterAt(
      intptr_t index,
      Nullability nullability = Nullability::kNonNullable) const;

  // The type argument vector is flattened and includes the type arguments of
  // the super class.
  intptr_t NumTypeArguments() const;

  // Return true if this class declares type parameters.
  bool IsGeneric() const {
    // If the declaration is not loaded, fall back onto NumTypeParameters.
    if (!is_declaration_loaded()) {
      return NumTypeParameters(Thread::Current()) > 0;
    }
    return type_parameters() != Object::null();
  }

  // Returns a canonicalized vector of the type parameters instantiated
  // to bounds. If non-generic, the empty type arguments vector is returned.
  TypeArgumentsPtr InstantiateToBounds(Thread* thread) const;

  // If this class is parameterized, each instance has a type_arguments field.
  static const intptr_t kNoTypeArguments = -1;
  intptr_t host_type_arguments_field_offset() const {
    ASSERT(is_type_finalized() || is_prefinalized());
    if (untag()->host_type_arguments_field_offset_in_words_ ==
        kNoTypeArguments) {
      return kNoTypeArguments;
    }
    return untag()->host_type_arguments_field_offset_in_words_ *
           kCompressedWordSize;
  }
  intptr_t target_type_arguments_field_offset() const {
#if defined(DART_PRECOMPILER)
    ASSERT(is_type_finalized() || is_prefinalized());
    if (untag()->target_type_arguments_field_offset_in_words_ ==
        compiler::target::Class::kNoTypeArguments) {
      return compiler::target::Class::kNoTypeArguments;
    }
    return untag()->target_type_arguments_field_offset_in_words_ *
           compiler::target::kCompressedWordSize;
#else
    return host_type_arguments_field_offset();
#endif  // defined(DART_PRECOMPILER)
  }
  void set_type_arguments_field_offset(intptr_t host_value_in_bytes,
                                       intptr_t target_value_in_bytes) const {
    intptr_t host_value, target_value;
    if (host_value_in_bytes == kNoTypeArguments ||
        target_value_in_bytes == RTN::Class::kNoTypeArguments) {
      ASSERT(host_value_in_bytes == kNoTypeArguments &&
             target_value_in_bytes == RTN::Class::kNoTypeArguments);
      host_value = kNoTypeArguments;
      target_value = RTN::Class::kNoTypeArguments;
    } else {
      ASSERT(kCompressedWordSize != 0 && compiler::target::kCompressedWordSize);
      host_value = host_value_in_bytes / kCompressedWordSize;
      target_value =
          target_value_in_bytes / compiler::target::kCompressedWordSize;
    }
    set_type_arguments_field_offset_in_words(host_value, target_value);
  }
  void set_type_arguments_field_offset_in_words(intptr_t host_value,
                                                intptr_t target_value) const {
    StoreNonPointer(&untag()->host_type_arguments_field_offset_in_words_,
                    host_value);
#if defined(DART_PRECOMPILER)
    StoreNonPointer(&untag()->target_type_arguments_field_offset_in_words_,
                    target_value);
#else
    // Could be different only during cross-compilation.
    ASSERT_EQUAL(host_value, target_value);
#endif  // defined(DART_PRECOMPILER)
  }
  static intptr_t host_type_arguments_field_offset_in_words_offset() {
    return OFFSET_OF(UntaggedClass, host_type_arguments_field_offset_in_words_);
  }

  // The super type of this class, Object type if not explicitly specified.
  AbstractTypePtr super_type() const {
    ASSERT(is_declaration_loaded());
    return untag()->super_type();
  }
  void set_super_type(const AbstractType& value) const;
  static intptr_t super_type_offset() {
    return OFFSET_OF(UntaggedClass, super_type_);
  }

  // Asserts that the class of the super type has been resolved.
  // |original_classes| only has an effect when reloading. If true and we
  // are reloading, it will prefer the original classes to the replacement
  // classes.
  ClassPtr SuperClass(bool original_classes = false) const;

  // Interfaces is an array of Types.
  ArrayPtr interfaces() const {
    ASSERT(is_declaration_loaded());
    return untag()->interfaces();
  }
  void set_interfaces(const Array& value) const;

  // Returns whether a path from [this] to [cls] can be found, where the first
  // element is a direct supertype of [this], each following element is a direct
  // supertype of the previous element and the final element has [cls] as its
  // type class. If [this] and [cls] are the same class, then the path is empty.
  //
  // If [path] is not nullptr, then the elements of the path are added to it.
  // This path can then be used to compute type arguments of [cls] given type
  // arguments for an instance of [this].
  //
  // Note: There may be multiple paths to [cls], but the result of applying each
  // path must be equal to the other results.
  bool FindInstantiationOf(Zone* zone,
                           const Class& cls,
                           GrowableArray<const AbstractType*>* path,
                           bool consider_only_super_classes = false) const;
  bool FindInstantiationOf(Zone* zone,
                           const Class& cls,
                           bool consider_only_super_classes = false) const {
    return FindInstantiationOf(zone, cls, /*path=*/nullptr,
                               consider_only_super_classes);
  }

  // Returns whether a path from [this] to [type] can be found, where the first
  // element is a direct supertype of [this], each following element is a direct
  // supertype of the previous element and the final element has the same type
  // class as [type]. If [this] is the type class of [type], then the path is
  // empty.
  //
  // If [path] is not nullptr, then the elements of the path are added to it.
  // This path can then be used to compute type arguments of [type]'s type
  // class given type arguments for an instance of [this].
  //
  // Note: There may be multiple paths to [type]'s type class, but the result of
  // applying each path must be equal to the other results.
  bool FindInstantiationOf(Zone* zone,
                           const Type& type,
                           GrowableArray<const AbstractType*>* path,
                           bool consider_only_super_classes = false) const;
  bool FindInstantiationOf(Zone* zone,
                           const Type& type,
                           bool consider_only_super_classes = false) const {
    return FindInstantiationOf(zone, type, /*path=*/nullptr,
                               consider_only_super_classes);
  }

  // If [this] is a subtype of a type with type class [cls], then this
  // returns [cls]<X_0, ..., X_n>, where n is the number of type arguments for
  // [cls] and where each type argument X_k is either instantiated or has free
  // class type parameters corresponding to the type parameters of [this].
  // Thus, given an instance of [this], the result can be instantiated
  // with the instance type arguments to get the type of the instance.
  //
  // If [this] is not a subtype of a type with type class [cls], returns null.
  TypePtr GetInstantiationOf(Zone* zone, const Class& cls) const;

  // If [this] is a subtype of [type], then this returns [cls]<X_0, ..., X_n>,
  // where [cls] is the type class of [type], n is the number of type arguments
  // for [cls], and where each type argument X_k is either instantiated or has
  // free class type parameters corresponding to the type parameters of [this].
  // Thus, given an instance of [this], the result can be instantiated with the
  // instance type arguments to get the type of the instance.
  //
  // If [this] is not a subtype of a type with type class [cls], returns null.
  TypePtr GetInstantiationOf(Zone* zone, const Type& type) const;

#if !defined(PRODUCT) || !defined(DART_PRECOMPILED_RUNTIME)
  // Returns the list of classes directly implementing this class.
  GrowableObjectArrayPtr direct_implementors() const {
    DEBUG_ASSERT(
        IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
    return untag()->direct_implementors();
  }
  GrowableObjectArrayPtr direct_implementors_unsafe() const {
    return untag()->direct_implementors();
  }
#endif  // !defined(PRODUCT) || !defined(DART_PRECOMPILED_RUNTIME)

#if !defined(DART_PRECOMPILED_RUNTIME)
  void set_direct_implementors(const GrowableObjectArray& implementors) const;
  void AddDirectImplementor(const Class& subclass, bool is_mixin) const;
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

#if !defined(PRODUCT) || !defined(DART_PRECOMPILED_RUNTIME)
  // Returns the list of classes having this class as direct superclass.
  GrowableObjectArrayPtr direct_subclasses() const {
    DEBUG_ASSERT(
        IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
    return direct_subclasses_unsafe();
  }
  GrowableObjectArrayPtr direct_subclasses_unsafe() const {
    return untag()->direct_subclasses();
  }
#endif  // !defined(PRODUCT) || !defined(DART_PRECOMPILED_RUNTIME)

#if !defined(DART_PRECOMPILED_RUNTIME)
  void set_direct_subclasses(const GrowableObjectArray& subclasses) const;
  void AddDirectSubclass(const Class& subclass) const;
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

  // Check if this class represents the class of null.
  bool IsNullClass() const { return id() == kNullCid; }

  // Check if this class represents the 'dynamic' class.
  bool IsDynamicClass() const { return id() == kDynamicCid; }

  // Check if this class represents the 'void' class.
  bool IsVoidClass() const { return id() == kVoidCid; }

  // Check if this class represents the 'Never' class.
  bool IsNeverClass() const { return id() == kNeverCid; }

  // Check if this class represents the 'Object' class.
  bool IsObjectClass() const { return id() == kInstanceCid; }

  // Check if this class represents the 'Function' class.
  bool IsDartFunctionClass() const;

  // Check if this class represents the 'Future' class.
  bool IsFutureClass() const;

  // Check if this class represents the 'FutureOr' class.
  bool IsFutureOrClass() const { return id() == kFutureOrCid; }

  // Check if this class represents the 'Closure' class.
  bool IsClosureClass() const { return id() == kClosureCid; }
  static bool IsClosureClass(ClassPtr cls) {
    return GetClassId(cls) == kClosureCid;
  }

  static bool IsInFullSnapshot(ClassPtr cls) {
    NoSafepointScope no_safepoint;
    return UntaggedLibrary::InFullSnapshotBit::decode(
        cls->untag()->library()->untag()->flags_);
  }

  static intptr_t GetClassId(ClassPtr cls) {
    NoSafepointScope no_safepoint;
    return cls->untag()->id_;
  }

  // Returns true if the type specified by cls, type_arguments, and nullability
  // is a subtype of the other type.
  static bool IsSubtypeOf(const Class& cls,
                          const TypeArguments& type_arguments,
                          Nullability nullability,
                          const AbstractType& other,
                          Heap::Space space,
                          TrailPtr trail = nullptr);

  // Check if this is the top level class.
  bool IsTopLevel() const;

  bool IsPrivate() const;

  DART_WARN_UNUSED_RESULT
  ErrorPtr VerifyEntryPoint() const;

  // Returns an array of instance and static fields defined by this class.
  ArrayPtr fields() const {
    // We rely on the fact that any loads from the array are dependent loads
    // and avoid the load-acquire barrier here.
    return untag()->fields();
  }
  void SetFields(const Array& value) const;
  void AddField(const Field& field) const;
  void AddFields(const GrowableArray<const Field*>& fields) const;

  // If this is a dart:internal.ClassID class, then inject our own const
  // fields. Returns true if synthetic fields are injected and regular
  // field declarations should be ignored.
  bool InjectCIDFields() const;

  // Returns an array of all instance fields of this class and its superclasses
  // indexed by offset in words.
  // |original_classes| only has an effect when reloading. If true and we
  // are reloading, it will prefer the original classes to the replacement
  // classes.
  ArrayPtr OffsetToFieldMap(bool original_classes = false) const;

  // Returns true if non-static fields are defined.
  bool HasInstanceFields() const;

  ArrayPtr current_functions() const {
    // We rely on the fact that any loads from the array are dependent loads
    // and avoid the load-acquire barrier here.
    return untag()->functions();
  }
  ArrayPtr functions() const {
    DEBUG_ASSERT(
        IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
    return current_functions();
  }
  void SetFunctions(const Array& value) const;
  void AddFunction(const Function& function) const;
  FunctionPtr FunctionFromIndex(intptr_t idx) const;
  intptr_t FindImplicitClosureFunctionIndex(const Function& needle) const;
  FunctionPtr ImplicitClosureFunctionFromIndex(intptr_t idx) const;

  FunctionPtr LookupFunctionReadLocked(const String& name) const;
  FunctionPtr LookupDynamicFunctionUnsafe(const String& name) const;

  FunctionPtr LookupDynamicFunctionAllowPrivate(const String& name) const;
  FunctionPtr LookupStaticFunction(const String& name) const;
  FunctionPtr LookupStaticFunctionAllowPrivate(const String& name) const;
  FunctionPtr LookupConstructor(const String& name) const;
  FunctionPtr LookupConstructorAllowPrivate(const String& name) const;
  FunctionPtr LookupFactory(const String& name) const;
  FunctionPtr LookupFactoryAllowPrivate(const String& name) const;
  FunctionPtr LookupFunctionAllowPrivate(const String& name) const;
  FunctionPtr LookupGetterFunction(const String& name) const;
  FunctionPtr LookupSetterFunction(const String& name) const;
  FieldPtr LookupInstanceField(const String& name) const;
  FieldPtr LookupStaticField(const String& name) const;
  FieldPtr LookupField(const String& name) const;
  FieldPtr LookupFieldAllowPrivate(const String& name,
                                   bool instance_only = false) const;
  FieldPtr LookupInstanceFieldAllowPrivate(const String& name) const;
  FieldPtr LookupStaticFieldAllowPrivate(const String& name) const;

  // The methods above are more efficient than this generic one.
  InstancePtr LookupCanonicalInstance(Zone* zone, const Instance& value) const;

  InstancePtr InsertCanonicalConstant(Zone* zone,
                                      const Instance& constant) const;

  void RehashConstants(Zone* zone) const;

  bool RequireCanonicalTypeErasureOfConstants(Zone* zone) const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedClass));
  }

  bool is_implemented() const { return ImplementedBit::decode(state_bits()); }
  void set_is_implemented() const;
  void set_is_implemented_unsafe() const;

  bool is_abstract() const { return AbstractBit::decode(state_bits()); }
  void set_is_abstract() const;

  UntaggedClass::ClassLoadingState class_loading_state() const {
    return ClassLoadingBits::decode(state_bits());
  }

  bool is_declaration_loaded() const {
    return class_loading_state() >= UntaggedClass::kDeclarationLoaded;
  }
  void set_is_declaration_loaded() const;
  void set_is_declaration_loaded_unsafe() const;

  bool is_type_finalized() const {
    return class_loading_state() >= UntaggedClass::kTypeFinalized;
  }
  void set_is_type_finalized() const;

  bool is_synthesized_class() const {
    return SynthesizedClassBit::decode(state_bits());
  }
  void set_is_synthesized_class() const;
  void set_is_synthesized_class_unsafe() const;

  bool is_enum_class() const { return EnumBit::decode(state_bits()); }
  void set_is_enum_class() const;

  bool is_finalized() const {
    return ClassFinalizedBits::decode(state_bits()) ==
               UntaggedClass::kFinalized ||
           ClassFinalizedBits::decode(state_bits()) ==
               UntaggedClass::kAllocateFinalized;
  }
  void set_is_finalized() const;
  void set_is_finalized_unsafe() const;

  bool is_allocate_finalized() const {
    return ClassFinalizedBits::decode(state_bits()) ==
           UntaggedClass::kAllocateFinalized;
  }
  void set_is_allocate_finalized() const;

  bool is_prefinalized() const {
    return ClassFinalizedBits::decode(state_bits()) ==
           UntaggedClass::kPreFinalized;
  }

  void set_is_prefinalized() const;

  bool is_const() const { return ConstBit::decode(state_bits()); }
  void set_is_const() const;

  // Tests if this is a mixin application class which was desugared
  // to a normal class by kernel mixin transformation
  // (pkg/kernel/lib/transformations/mixin_full_resolution.dart).
  //
  // In such case, its mixed-in type was pulled into the end of
  // interfaces list.
  bool is_transformed_mixin_application() const {
    return TransformedMixinApplicationBit::decode(state_bits());
  }
  void set_is_transformed_mixin_application() const;

  bool is_fields_marked_nullable() const {
    return FieldsMarkedNullableBit::decode(state_bits());
  }
  void set_is_fields_marked_nullable() const;

  bool is_allocated() const { return IsAllocatedBit::decode(state_bits()); }
  void set_is_allocated(bool value) const;
  void set_is_allocated_unsafe(bool value) const;

  bool is_loaded() const { return IsLoadedBit::decode(state_bits()); }
  void set_is_loaded(bool value) const;

  uint16_t num_native_fields() const { return untag()->num_native_fields_; }
  void set_num_native_fields(uint16_t value) const {
    StoreNonPointer(&untag()->num_native_fields_, value);
  }
  static uint16_t NumNativeFieldsOf(ClassPtr clazz) {
    return clazz->untag()->num_native_fields_;
  }
  static bool ImplementsFinalizable(ClassPtr clazz) {
    ASSERT(Class::Handle(clazz).is_type_finalized());
    return ImplementsFinalizableBit::decode(clazz->untag()->state_bits_);
  }

#if !defined(DART_PRECOMPILED_RUNTIME)
  CodePtr allocation_stub() const { return untag()->allocation_stub(); }
  void set_allocation_stub(const Code& value) const;
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

  intptr_t kernel_offset() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    return 0;
#else
    return untag()->kernel_offset_;
#endif
  }

  void set_kernel_offset(intptr_t value) const {
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
#else
    ASSERT(value >= 0);
    StoreNonPointer(&untag()->kernel_offset_, value);
#endif
  }

  void DisableAllocationStub() const;

  ArrayPtr constants() const;
  void set_constants(const Array& value) const;

  intptr_t FindInvocationDispatcherFunctionIndex(const Function& needle) const;
  FunctionPtr InvocationDispatcherFunctionFromIndex(intptr_t idx) const;

  FunctionPtr GetInvocationDispatcher(const String& target_name,
                                      const Array& args_desc,
                                      UntaggedFunction::Kind kind,
                                      bool create_if_absent) const;

  void Finalize() const;

  ObjectPtr Invoke(const String& selector,
                   const Array& arguments,
                   const Array& argument_names,
                   bool respect_reflectable = true,
                   bool check_is_entrypoint = false) const;
  ObjectPtr InvokeGetter(const String& selector,
                         bool throw_nsm_if_absent,
                         bool respect_reflectable = true,
                         bool check_is_entrypoint = false) const;
  ObjectPtr InvokeSetter(const String& selector,
                         const Instance& argument,
                         bool respect_reflectable = true,
                         bool check_is_entrypoint = false) const;

  // Evaluate the given expression as if it appeared in a static method of this
  // class and return the resulting value, or an error object if evaluating the
  // expression fails. The method has the formal (type) parameters given in
  // (type_)param_names, and is invoked with the (type)argument values given in
  // (type_)param_values.
  ObjectPtr EvaluateCompiledExpression(
      const ExternalTypedData& kernel_buffer,
      const Array& type_definitions,
      const Array& param_values,
      const TypeArguments& type_param_values) const;

  // Load class declaration (super type, interfaces, type parameters and
  // number of type arguments) if it is not loaded yet.
  void EnsureDeclarationLoaded() const;

  ErrorPtr EnsureIsFinalized(Thread* thread) const;
  ErrorPtr EnsureIsAllocateFinalized(Thread* thread) const;

  // Allocate a class used for VM internal objects.
  template <class FakeObject, class TargetFakeObject>
  static ClassPtr New(IsolateGroup* isolate_group, bool register_class = true);

  // Allocate instance classes.
  static ClassPtr New(const Library& lib,
                      const String& name,
                      const Script& script,
                      TokenPosition token_pos,
                      bool register_class = true);
  static ClassPtr NewNativeWrapper(const Library& library,
                                   const String& name,
                                   int num_fields);

  // Allocate the raw string classes.
  static ClassPtr NewStringClass(intptr_t class_id,
                                 IsolateGroup* isolate_group);

  // Allocate the raw TypedData classes.
  static ClassPtr NewTypedDataClass(intptr_t class_id,
                                    IsolateGroup* isolate_group);

  // Allocate the raw TypedDataView/ByteDataView classes.
  static ClassPtr NewTypedDataViewClass(intptr_t class_id,
                                        IsolateGroup* isolate_group);

  // Allocate the raw ExternalTypedData classes.
  static ClassPtr NewExternalTypedDataClass(intptr_t class_id,
                                            IsolateGroup* isolate);

  // Allocate the raw Pointer classes.
  static ClassPtr NewPointerClass(intptr_t class_id,
                                  IsolateGroup* isolate_group);

#if !defined(DART_PRECOMPILED_RUNTIME)
  // Register code that has used CHA for optimization.
  // TODO(srdjan): Also register kind of CHA optimization (e.g.: leaf class,
  // leaf method, ...).
  void RegisterCHACode(const Code& code);

  void DisableCHAOptimizedCode(const Class& subclass);

  void DisableAllCHAOptimizedCode();

  void DisableCHAImplementorUsers() { DisableAllCHAOptimizedCode(); }

  // Return the list of code objects that were compiled using CHA of this class.
  // These code objects will be invalidated if new subclasses of this class
  // are finalized.
  ArrayPtr dependent_code() const;
  void set_dependent_code(const Array& array) const;
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

  bool TraceAllocation(IsolateGroup* isolate_group) const;
  void SetTraceAllocation(bool trace_allocation) const;

  void ReplaceEnum(ProgramReloadContext* reload_context,
                   const Class& old_enum) const;
  void CopyStaticFieldValues(ProgramReloadContext* reload_context,
                             const Class& old_cls) const;
  void PatchFieldsAndFunctions() const;
  void MigrateImplicitStaticClosures(ProgramReloadContext* context,
                                     const Class& new_cls) const;
  void CopyCanonicalConstants(const Class& old_cls) const;
  void CopyDeclarationType(const Class& old_cls) const;
  void CheckReload(const Class& replacement,
                   ProgramReloadContext* context) const;

  void AddInvocationDispatcher(const String& target_name,
                               const Array& args_desc,
                               const Function& dispatcher) const;

  static int32_t host_instance_size_in_words(const ClassPtr cls) {
    return cls->untag()->host_instance_size_in_words_;
  }

  static int32_t target_instance_size_in_words(const ClassPtr cls) {
#if defined(DART_PRECOMPILER)
    return cls->untag()->target_instance_size_in_words_;
#else
    return host_instance_size_in_words(cls);
#endif  // defined(DART_PRECOMPILER)
  }

  static int32_t host_next_field_offset_in_words(const ClassPtr cls) {
    return cls->untag()->host_next_field_offset_in_words_;
  }

  static int32_t target_next_field_offset_in_words(const ClassPtr cls) {
#if defined(DART_PRECOMPILER)
    return cls->untag()->target_next_field_offset_in_words_;
#else
    return host_next_field_offset_in_words(cls);
#endif  // defined(DART_PRECOMPILER)
  }

  static int32_t host_type_arguments_field_offset_in_words(const ClassPtr cls) {
    return cls->untag()->host_type_arguments_field_offset_in_words_;
  }

  static int32_t target_type_arguments_field_offset_in_words(
      const ClassPtr cls) {
#if defined(DART_PRECOMPILER)
    return cls->untag()->target_type_arguments_field_offset_in_words_;
#else
    return host_type_arguments_field_offset_in_words(cls);
#endif  // defined(DART_PRECOMPILER)
  }

 private:
  TypePtr declaration_type() const {
    return untag()->declaration_type<std::memory_order_acquire>();
  }

  // Caches the declaration type of this class.
  void set_declaration_type(const Type& type) const;

  bool CanReloadFinalized(const Class& replacement,
                          ProgramReloadContext* context) const;
  bool CanReloadPreFinalized(const Class& replacement,
                             ProgramReloadContext* context) const;

  // Tells whether instances need morphing for reload.
  bool RequiresInstanceMorphing(const Class& replacement) const;

  template <class FakeInstance, class TargetFakeInstance>
  static ClassPtr NewCommon(intptr_t index);

  enum MemberKind {
    kAny = 0,
    kStatic,
    kInstance,
    kInstanceAllowAbstract,
    kConstructor,
    kFactory,
  };
  enum StateBits {
    kConstBit = 0,
    kImplementedBit = 1,
    kClassFinalizedPos = 2,
    kClassFinalizedSize = 2,
    kClassLoadingPos = kClassFinalizedPos + kClassFinalizedSize,  // = 4
    kClassLoadingSize = 2,
    kAbstractBit = kClassLoadingPos + kClassLoadingSize,  // = 6
    kSynthesizedClassBit,
    kMixinAppAliasBit,
    kMixinTypeAppliedBit,
    kFieldsMarkedNullableBit,
    kEnumBit,
    kTransformedMixinApplicationBit,
    kIsAllocatedBit,
    kIsLoadedBit,
    kHasPragmaBit,
    kImplementsFinalizableBit,
  };
  class ConstBit : public BitField<uint32_t, bool, kConstBit, 1> {};
  class ImplementedBit : public BitField<uint32_t, bool, kImplementedBit, 1> {};
  class ClassFinalizedBits : public BitField<uint32_t,
                                             UntaggedClass::ClassFinalizedState,
                                             kClassFinalizedPos,
                                             kClassFinalizedSize> {};
  class ClassLoadingBits : public BitField<uint32_t,
                                           UntaggedClass::ClassLoadingState,
                                           kClassLoadingPos,
                                           kClassLoadingSize> {};
  class AbstractBit : public BitField<uint32_t, bool, kAbstractBit, 1> {};
  class SynthesizedClassBit
      : public BitField<uint32_t, bool, kSynthesizedClassBit, 1> {};
  class FieldsMarkedNullableBit
      : public BitField<uint32_t, bool, kFieldsMarkedNullableBit, 1> {};
  class EnumBit : public BitField<uint32_t, bool, kEnumBit, 1> {};
  class TransformedMixinApplicationBit
      : public BitField<uint32_t, bool, kTransformedMixinApplicationBit, 1> {};
  class IsAllocatedBit : public BitField<uint32_t, bool, kIsAllocatedBit, 1> {};
  class IsLoadedBit : public BitField<uint32_t, bool, kIsLoadedBit, 1> {};
  class HasPragmaBit : public BitField<uint32_t, bool, kHasPragmaBit, 1> {};
  class ImplementsFinalizableBit
      : public BitField<uint32_t, bool, kImplementsFinalizableBit, 1> {};

  void set_name(const String& value) const;
  void set_user_name(const String& value) const;
  const char* GenerateUserVisibleName() const;
  void set_state_bits(intptr_t bits) const;

  FunctionPtr CreateInvocationDispatcher(const String& target_name,
                                         const Array& args_desc,
                                         UntaggedFunction::Kind kind) const;

  // Returns the bitmap of unboxed fields
  UnboxedFieldBitmap CalculateFieldOffsets() const;

  // functions_hash_table is in use iff there are at least this many functions.
  static const intptr_t kFunctionLookupHashTreshold = 16;

  // Initial value for the cached number of type arguments.
  static const intptr_t kUnknownNumTypeArguments = -1;

  int16_t num_type_arguments() const {
    return LoadNonPointer<int16_t, std::memory_order_relaxed>(
        &untag()->num_type_arguments_);
  }

  uint32_t state_bits() const {
    // Ensure any following load instructions do not get performed before this
    // one.
    return LoadNonPointer<uint32_t, std::memory_order_acquire>(
        &untag()->state_bits_);
  }

 public:
  void set_num_type_arguments(intptr_t value) const;
  void set_num_type_arguments_unsafe(intptr_t value) const;

  bool has_pragma() const { return HasPragmaBit::decode(state_bits()); }
  void set_has_pragma(bool has_pragma) const;

  bool implements_finalizable() const {
    ASSERT(is_type_finalized());
    return ImplementsFinalizable(ptr());
  }
  void set_implements_finalizable(bool value) const;

 private:
  void set_functions(const Array& value) const;
  void set_fields(const Array& value) const;
  void set_invocation_dispatcher_cache(const Array& cache) const;

  ArrayPtr invocation_dispatcher_cache() const;

  // Calculates number of type arguments of this class.
  // This includes type arguments of a superclass and takes overlapping
  // of type arguments into account.
  intptr_t ComputeNumTypeArguments() const;

  // Assigns empty array to all raw class array fields.
  void InitEmptyFields();

  static FunctionPtr CheckFunctionType(const Function& func, MemberKind kind);
  FunctionPtr LookupFunctionReadLocked(const String& name,
                                       MemberKind kind) const;
  FunctionPtr LookupFunctionAllowPrivate(const String& name,
                                         MemberKind kind) const;
  FieldPtr LookupField(const String& name, MemberKind kind) const;

  FunctionPtr LookupAccessorFunction(const char* prefix,
                                     intptr_t prefix_length,
                                     const String& name) const;

  // Allocate an instance class which has a VM implementation.
  template <class FakeInstance, class TargetFakeInstance>
  static ClassPtr New(intptr_t id,
                      IsolateGroup* isolate_group,
                      bool register_class = true,
                      bool is_abstract = false);

  // Helper that calls 'Class::New<Instance>(kIllegalCid)'.
  static ClassPtr NewInstanceClass();

  FINAL_HEAP_OBJECT_IMPLEMENTATION(Class, Object);
  friend class AbstractType;
  friend class Instance;
  friend class Object;
  friend class Type;
  friend class Intrinsifier;
  friend class ProgramWalker;
  friend class Precompiler;
  friend class ClassFinalizer;
};

// Classification of type genericity according to type parameter owners.
enum Genericity {
  kAny,           // Consider type params of current class and functions.
  kCurrentClass,  // Consider type params of current class only.
  kFunctions,     // Consider type params of current and parent functions.
};

class PatchClass : public Object {
 public:
  ClassPtr patched_class() const { return untag()->patched_class(); }
  ClassPtr origin_class() const { return untag()->origin_class(); }
  ScriptPtr script() const { return untag()->script(); }
  ExternalTypedDataPtr library_kernel_data() const {
    return untag()->library_kernel_data();
  }
  void set_library_kernel_data(const ExternalTypedData& data) const;

  intptr_t library_kernel_offset() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
    return untag()->library_kernel_offset_;
#else
    return -1;
#endif
  }
  void set_library_kernel_offset(intptr_t offset) const {
    NOT_IN_PRECOMPILED(
        StoreNonPointer(&untag()->library_kernel_offset_, offset));
  }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedPatchClass));
  }
  static bool IsInFullSnapshot(PatchClassPtr cls) {
    NoSafepointScope no_safepoint;
    return Class::IsInFullSnapshot(cls->untag()->patched_class());
  }

  static PatchClassPtr New(const Class& patched_class,
                           const Class& origin_class);

  static PatchClassPtr New(const Class& patched_class, const Script& source);

 private:
  void set_patched_class(const Class& value) const;
  void set_origin_class(const Class& value) const;
  void set_script(const Script& value) const;

  static PatchClassPtr New();

  FINAL_HEAP_OBJECT_IMPLEMENTATION(PatchClass, Object);
  friend class Class;
};

class SingleTargetCache : public Object {
 public:
  CodePtr target() const { return untag()->target(); }
  void set_target(const Code& target) const;
  static intptr_t target_offset() {
    return OFFSET_OF(UntaggedSingleTargetCache, target_);
  }

#define DEFINE_NON_POINTER_FIELD_ACCESSORS(type, name)                         \
  type name() const { return untag()->name##_; }                               \
  void set_##name(type value) const {                                          \
    StoreNonPointer(&untag()->name##_, value);                                 \
  }                                                                            \
  static intptr_t name##_offset() {                                            \
    return OFFSET_OF(UntaggedSingleTargetCache, name##_);                      \
  }

  DEFINE_NON_POINTER_FIELD_ACCESSORS(uword, entry_point);
  DEFINE_NON_POINTER_FIELD_ACCESSORS(intptr_t, lower_limit);
  DEFINE_NON_POINTER_FIELD_ACCESSORS(intptr_t, upper_limit);
#undef DEFINE_NON_POINTER_FIELD_ACCESSORS

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedSingleTargetCache));
  }

  static SingleTargetCachePtr New();

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(SingleTargetCache, Object);
  friend class Class;
};

class MonomorphicSmiableCall : public Object {
 public:
  classid_t expected_cid() const { return untag()->expected_cid_; }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedMonomorphicSmiableCall));
  }

  static MonomorphicSmiableCallPtr New(classid_t expected_cid,
                                       const Code& target);

  static intptr_t expected_cid_offset() {
    return OFFSET_OF(UntaggedMonomorphicSmiableCall, expected_cid_);
  }

  static intptr_t entrypoint_offset() {
    return OFFSET_OF(UntaggedMonomorphicSmiableCall, entrypoint_);
  }

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(MonomorphicSmiableCall, Object);
  friend class Class;
};

class CallSiteData : public Object {
 public:
  StringPtr target_name() const { return untag()->target_name(); }
  ArrayPtr arguments_descriptor() const { return untag()->args_descriptor(); }

  intptr_t TypeArgsLen() const;

  intptr_t CountWithTypeArgs() const;

  intptr_t CountWithoutTypeArgs() const;

  intptr_t SizeWithoutTypeArgs() const;

  intptr_t SizeWithTypeArgs() const;

  static intptr_t target_name_offset() {
    return OFFSET_OF(UntaggedCallSiteData, target_name_);
  }

  static intptr_t arguments_descriptor_offset() {
    return OFFSET_OF(UntaggedCallSiteData, args_descriptor_);
  }

 private:
  void set_target_name(const String& value) const;
  void set_arguments_descriptor(const Array& value) const;

  HEAP_OBJECT_IMPLEMENTATION(CallSiteData, Object)

  friend class ICData;
  friend class MegamorphicCache;
};

class UnlinkedCall : public CallSiteData {
 public:
  bool can_patch_to_monomorphic() const {
    return untag()->can_patch_to_monomorphic_;
  }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedUnlinkedCall));
  }

  uword Hash() const;
  bool Equals(const UnlinkedCall& other) const;

  static UnlinkedCallPtr New();

 private:
  friend class ICData;  // For set_*() methods.

  void set_can_patch_to_monomorphic(bool value) const;

  FINAL_HEAP_OBJECT_IMPLEMENTATION(UnlinkedCall, CallSiteData);
  friend class Class;
};

// Object holding information about an IC: test classes and their
// corresponding targets. The owner of the ICData can be either the function
// or the original ICData object. In case of background compilation we
// copy the ICData in a child object, thus freezing it during background
// compilation. Code may contain only original ICData objects.
class ICData : public CallSiteData {
 public:
  FunctionPtr Owner() const;

  ICDataPtr Original() const;

  void SetOriginal(const ICData& value) const;

  bool IsOriginal() const { return Original() == this->ptr(); }

  intptr_t NumArgsTested() const;

  intptr_t deopt_id() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
    return -1;
#else
    return untag()->deopt_id_;
#endif
  }

  bool IsImmutable() const;

#if !defined(DART_PRECOMPILED_RUNTIME)
  AbstractTypePtr receivers_static_type() const {
    return untag()->receivers_static_type();
  }
  bool is_tracking_exactness() const {
    return untag()->state_bits_.Read<TrackingExactnessBit>();
  }
#else
  bool is_tracking_exactness() const { return false; }
#endif

// Note: only deopts with reasons before Unknown in this list are recorded in
// the ICData. All other reasons are used purely for informational messages
// printed during deoptimization itself.
#define DEOPT_REASONS(V)                                                       \
  V(BinarySmiOp)                                                               \
  V(BinaryInt64Op)                                                             \
  V(DoubleToSmi)                                                               \
  V(CheckSmi)                                                                  \
  V(CheckClass)                                                                \
  V(Unknown)                                                                   \
  V(PolymorphicInstanceCallTestFail)                                           \
  V(UnaryInt64Op)                                                              \
  V(BinaryDoubleOp)                                                            \
  V(UnaryOp)                                                                   \
  V(UnboxInteger)                                                              \
  V(Unbox)                                                                     \
  V(CheckArrayBound)                                                           \
  V(AtCall)                                                                    \
  V(GuardField)                                                                \
  V(TestCids)                                                                  \
  V(NumReasons)

  enum DeoptReasonId {
#define DEFINE_ENUM_LIST(name) kDeopt##name,
    DEOPT_REASONS(DEFINE_ENUM_LIST)
#undef DEFINE_ENUM_LIST
  };

  static const intptr_t kLastRecordedDeoptReason = kDeoptUnknown - 1;

  enum DeoptFlags {
    // Deoptimization is caused by an optimistically hoisted instruction.
    kHoisted = 1 << 0,

    // Deoptimization is caused by an optimistically generalized bounds check.
    kGeneralized = 1 << 1
  };

  bool HasDeoptReasons() const { return DeoptReasons() != 0; }
  uint32_t DeoptReasons() const;
  void SetDeoptReasons(uint32_t reasons) const;

  bool HasDeoptReason(ICData::DeoptReasonId reason) const;
  void AddDeoptReason(ICData::DeoptReasonId reason) const;

  // Call site classification that is helpful for hot-reload. Call sites with
  // different `RebindRule` have to be rebound differently.
#define FOR_EACH_REBIND_RULE(V)                                                \
  V(Instance)                                                                  \
  V(NoRebind)                                                                  \
  V(NSMDispatch)                                                               \
  V(Optimized)                                                                 \
  V(Static)                                                                    \
  V(Super)

  enum RebindRule {
#define REBIND_ENUM_DEF(name) k##name,
    FOR_EACH_REBIND_RULE(REBIND_ENUM_DEF)
#undef REBIND_ENUM_DEF
        kNumRebindRules,
  };
  static const char* RebindRuleToCString(RebindRule r);
  static bool ParseRebindRule(const char* str, RebindRule* out);
  RebindRule rebind_rule() const;

  void set_is_megamorphic(bool value) const {
    untag()->state_bits_.UpdateBool<MegamorphicBit, std::memory_order_release>(
        value);
  }

  // The length of the array. This includes all sentinel entries including
  // the final one.
  intptr_t Length() const;

  // Takes O(result) time!
  intptr_t NumberOfChecks() const;

  // Discounts any checks with usage of zero.
  // Takes O(result)) time!
  intptr_t NumberOfUsedChecks() const;

  // Takes O(n) time!
  bool NumberOfChecksIs(intptr_t n) const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedICData));
  }

  static intptr_t state_bits_offset() {
    return OFFSET_OF(UntaggedICData, state_bits_);
  }

  static intptr_t NumArgsTestedShift() { return kNumArgsTestedPos; }

  static intptr_t NumArgsTestedMask() {
    return ((1 << kNumArgsTestedSize) - 1) << kNumArgsTestedPos;
  }

  static intptr_t entries_offset() {
    return OFFSET_OF(UntaggedICData, entries_);
  }

  static intptr_t owner_offset() { return OFFSET_OF(UntaggedICData, owner_); }

#if !defined(DART_PRECOMPILED_RUNTIME)
  static intptr_t receivers_static_type_offset() {
    return OFFSET_OF(UntaggedICData, receivers_static_type_);
  }
#endif

  // Replaces entry |index| with the sentinel.
  // NOTE: Can only be called during reload.
  void WriteSentinelAt(intptr_t index,
                       const CallSiteResetter& proof_of_reload) const;

  // Clears the count for entry |index|.
  // NOTE: Can only be called during reload.
  void ClearCountAt(intptr_t index,
                    const CallSiteResetter& proof_of_reload) const;

  // Clear all entries with the sentinel value and reset the first entry
  // with the dummy target entry.
  // NOTE: Can only be called during reload.
  void ClearAndSetStaticTarget(const Function& func,
                               const CallSiteResetter& proof_of_reload) const;

  void DebugDump() const;

  // Adding checks.

  // Ensures there is a check for [class_ids].
  //
  // Calls [AddCheck] iff there is no existing check. Ensures test (and
  // potential update) will be performed under exclusive lock to guard against
  // multiple threads trying to add the same check.
  void EnsureHasCheck(const GrowableArray<intptr_t>& class_ids,
                      const Function& target,
                      intptr_t count = 1) const;

  // Adds one more class test to ICData. Length of 'classes' must be equal to
  // the number of arguments tested. Use only for num_args_tested > 1.
  void AddCheck(const GrowableArray<intptr_t>& class_ids,
                const Function& target,
                intptr_t count = 1) const;

  StaticTypeExactnessState GetExactnessAt(intptr_t count) const;

  // Ensures there is a receiver check for [receiver_class_id].
  //
  // Calls [AddCheckReceiverCheck] iff there is no existing check. Ensures
  // test (and potential update) will be performed under exclusive lock to
  // guard against multiple threads trying to add the same check.
  void EnsureHasReceiverCheck(
      intptr_t receiver_class_id,
      const Function& target,
      intptr_t count = 1,
      StaticTypeExactnessState exactness =
          StaticTypeExactnessState::NotTracking()) const;

  // Adds sorted so that Smi is the first class-id. Use only for
  // num_args_tested == 1.
  void AddReceiverCheck(intptr_t receiver_class_id,
                        const Function& target,
                        intptr_t count = 1,
                        StaticTypeExactnessState exactness =
                            StaticTypeExactnessState::NotTracking()) const;

  // Retrieving checks.

  void GetCheckAt(intptr_t index,
                  GrowableArray<intptr_t>* class_ids,
                  Function* target) const;
  void GetClassIdsAt(intptr_t index, GrowableArray<intptr_t>* class_ids) const;

  // Only for 'num_args_checked == 1'.
  void GetOneClassCheckAt(intptr_t index,
                          intptr_t* class_id,
                          Function* target) const;
  // Only for 'num_args_checked == 1'.
  intptr_t GetCidAt(intptr_t index) const;

  intptr_t GetReceiverClassIdAt(intptr_t index) const;
  intptr_t GetClassIdAt(intptr_t index, intptr_t arg_nr) const;

  FunctionPtr GetTargetAt(intptr_t index) const;

  void IncrementCountAt(intptr_t index, intptr_t value) const;
  void SetCountAt(intptr_t index, intptr_t value) const;
  intptr_t GetCountAt(intptr_t index) const;
  intptr_t AggregateCount() const;

  // Returns this->untag() if num_args_tested == 1 and arg_nr == 1, otherwise
  // returns a new ICData object containing only unique arg_nr checks.
  // Returns only used entries.
  ICDataPtr AsUnaryClassChecksForArgNr(intptr_t arg_nr) const;
  ICDataPtr AsUnaryClassChecks() const { return AsUnaryClassChecksForArgNr(0); }

  // Returns ICData with aggregated receiver count, sorted by highest count.
  // Smi not first!! (the convention for ICData used in code generation is that
  // Smi check is first)
  // Used for printing and optimizations.
  ICDataPtr AsUnaryClassChecksSortedByCount() const;

  UnlinkedCallPtr AsUnlinkedCall() const;

  bool HasReceiverClassId(intptr_t class_id) const;

  // Note: passing non-null receiver_type enables exactness tracking for
  // the receiver type. Receiver type is expected to be a fully
  // instantiated generic (but not a FutureOr).
  // See StaticTypeExactnessState for more information.
  static ICDataPtr 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& receiver_type = Object::null_abstract_type());

  // Similar to [New] makes the ICData have an initial (cids, target) entry.
  static ICDataPtr 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 = Object::null_abstract_type());

  static ICDataPtr NewForStaticCall(const Function& owner,
                                    const Function& target,
                                    const Array& arguments_descriptor,
                                    intptr_t deopt_id,
                                    intptr_t num_args_tested,
                                    RebindRule rebind_rule);

  static ICDataPtr NewFrom(const ICData& from, intptr_t num_args_tested);

  // Generates a new ICData with descriptor and data array copied (deep clone).
  static ICDataPtr Clone(const ICData& from);

  // Gets the [ICData] from the [ICData::entries_] array (which stores a back
  // ref).
  //
  // May return `null` if the [ICData] is empty.
  static ICDataPtr ICDataOfEntriesArray(const Array& array);

  static intptr_t TestEntryLengthFor(intptr_t num_args,
                                     bool tracking_exactness);

  static intptr_t CountIndexFor(intptr_t num_args) { return num_args; }
  static intptr_t EntryPointIndexFor(intptr_t num_args) { return num_args; }

  static intptr_t TargetIndexFor(intptr_t num_args) { return num_args + 1; }
  static intptr_t CodeIndexFor(intptr_t num_args) { return num_args + 1; }

  static intptr_t ExactnessIndexFor(intptr_t num_args) { return num_args + 2; }

  bool IsUsedAt(intptr_t i) const;

  void PrintToJSONArray(const JSONArray& jsarray,
                        TokenPosition token_pos) const;

  // Initialize the preallocated empty ICData entry arrays.
  static void Init();

  // Clear the preallocated empty ICData entry arrays.
  static void Cleanup();

  // We cache ICData with 0, 1, 2 arguments tested without exactness
  // tracking and with 1 argument tested with exactness tracking.
  enum {
    kCachedICDataZeroArgTestedWithoutExactnessTrackingIdx = 0,
    kCachedICDataMaxArgsTestedWithoutExactnessTracking = 2,
    kCachedICDataOneArgWithExactnessTrackingIdx =
        kCachedICDataZeroArgTestedWithoutExactnessTrackingIdx +
        kCachedICDataMaxArgsTestedWithoutExactnessTracking + 1,
    kCachedICDataArrayCount = kCachedICDataOneArgWithExactnessTrackingIdx + 1,
  };

  bool is_static_call() const;

  intptr_t FindCheck(const GrowableArray<intptr_t>& cids) const;

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

  bool receiver_cannot_be_smi() const {
    return untag()->state_bits_.Read<ReceiverCannotBeSmiBit>();
  }

  void set_receiver_cannot_be_smi(bool value) const {
    untag()->state_bits_.UpdateBool<ReceiverCannotBeSmiBit>(value);
  }

  uword Hash() const;

 private:
  static ICDataPtr New();

  // Grows the array and also sets the argument to the index that should be used
  // for the new entry.
  ArrayPtr Grow(intptr_t* index) const;

  void set_deopt_id(intptr_t value) const;
  void set_entries(const Array& value) const;
  void set_owner(const Function& value) const;
  void set_rebind_rule(uint32_t rebind_rule) const;
  void clear_state_bits() const;
  void set_tracking_exactness(bool value) const {
    untag()->state_bits_.UpdateBool<TrackingExactnessBit>(value);
  }

  // Does entry |index| contain the sentinel value?
  bool IsSentinelAt(intptr_t index) const;
  void SetNumArgsTested(intptr_t value) const;
  void SetReceiversStaticType(const AbstractType& type) const;

  static void SetTargetAtPos(const Array& data,
                             intptr_t data_pos,
                             intptr_t num_args_tested,
                             const Function& target);
  void AddCheckInternal(const GrowableArray<intptr_t>& class_ids,
                        const Function& target,
                        intptr_t count) const;
  void AddReceiverCheckInternal(intptr_t receiver_class_id,
                                const Function& target,
                                intptr_t count,
                                StaticTypeExactnessState exactness) const;

  // This bit is set when a call site becomes megamorphic and starts using a
  // MegamorphicCache instead of ICData. It means that the entries in the
  // ICData are incomplete and the MegamorphicCache needs to also be consulted
  // to list the call site's observed receiver classes and targets.
  // In the compiler, this should only be read once by CallTargets to avoid the
  // compiler seeing an unstable set of feedback.
  bool is_megamorphic() const {
    // Ensure any following load instructions do not get performed before this
    // one.
    return untag()
        ->state_bits_.Read<MegamorphicBit, std::memory_order_acquire>();
  }

  bool ValidateInterceptor(const Function& target) const;

  enum {
    kNumArgsTestedPos = 0,
    kNumArgsTestedSize = 2,
    kTrackingExactnessPos = kNumArgsTestedPos + kNumArgsTestedSize,
    kTrackingExactnessSize = 1,
    kDeoptReasonPos = kTrackingExactnessPos + kTrackingExactnessSize,
    kDeoptReasonSize = kLastRecordedDeoptReason + 1,
    kRebindRulePos = kDeoptReasonPos + kDeoptReasonSize,
    kRebindRuleSize = 3,
    kMegamorphicPos = kRebindRulePos + kRebindRuleSize,
    kMegamorphicSize = 1,
    kReceiverCannotBeSmiPos = kMegamorphicPos + kMegamorphicSize,
    kReceiverCannotBeSmiSize = 1,
  };

  COMPILE_ASSERT(kReceiverCannotBeSmiPos + kReceiverCannotBeSmiSize <=
                 sizeof(UntaggedICData::state_bits_) * kBitsPerWord);
  COMPILE_ASSERT(kNumRebindRules <= (1 << kRebindRuleSize));

  class NumArgsTestedBits : public BitField<uint32_t,
                                            uint32_t,
                                            kNumArgsTestedPos,
                                            kNumArgsTestedSize> {};
  class TrackingExactnessBit : public BitField<uint32_t,
                                               bool,
                                               kTrackingExactnessPos,
                                               kTrackingExactnessSize> {};
  class DeoptReasonBits : public BitField<uint32_t,
                                          uint32_t,
                                          ICData::kDeoptReasonPos,
                                          ICData::kDeoptReasonSize> {};
  class RebindRuleBits : public BitField<uint32_t,
                                         uint32_t,
                                         ICData::kRebindRulePos,
                                         ICData::kRebindRuleSize> {};
  class MegamorphicBit
      : public BitField<uint32_t, bool, kMegamorphicPos, kMegamorphicSize> {};

  class ReceiverCannotBeSmiBit : public BitField<uint32_t,
                                                 bool,
                                                 kReceiverCannotBeSmiPos,
                                                 kReceiverCannotBeSmiSize> {};

#if defined(DEBUG)
  // Used in asserts to verify that a check is not added twice.
  bool HasCheck(const GrowableArray<intptr_t>& cids) const;
#endif  // DEBUG

  intptr_t TestEntryLength() const;
  static ArrayPtr NewNonCachedEmptyICDataArray(intptr_t num_args_tested,
                                               bool tracking_exactness);
  static ArrayPtr CachedEmptyICDataArray(intptr_t num_args_tested,
                                         bool tracking_exactness);
  static ICDataPtr 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& receiver_type);

  static void WriteSentinel(const Array& data,
                            intptr_t test_entry_length,
                            const Object& back_ref);

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

  FINAL_HEAP_OBJECT_IMPLEMENTATION(ICData, CallSiteData);
  friend class CallSiteResetter;
  friend class CallTargets;
  friend class Class;
  friend class VMDeserializationRoots;
  friend class ICDataTestTask;
  friend class VMSerializationRoots;
};

// Often used constants for number of free function type parameters.
enum {
  kNoneFree = 0,

  // 'kCurrentAndEnclosingFree' is used when partially applying a signature
  // function to a set of type arguments. It indicates that the set of type
  // parameters declared by the current function and enclosing functions should
  // be considered free, and the current function type parameters should be
  // substituted as well.
  //
  // For instance, if the signature "<T>(T, R) => T" is instantiated with
  // function type arguments [int, String] and kCurrentAndEnclosingFree is
  // supplied, the result of the instantiation will be "(String, int) => int".
  kCurrentAndEnclosingFree = kMaxInt32 - 1,

  // Only parameters declared by enclosing functions are free.
  kAllFree = kMaxInt32,
};

// Formatting configuration for Function::PrintName.
struct NameFormattingParams {
  Object::NameVisibility name_visibility;
  bool disambiguate_names;

  // By default function name includes the name of the enclosing class if any.
  // However in some contexts this information is redundant and class name
  // is already known. In this case setting |include_class_name| to false
  // allows you to exclude this information from the formatted name.
  bool include_class_name = true;

  // By default function name includes the name of the enclosing function if
  // any. However in some contexts this information is redundant and
  // the name of the enclosing function is already known. In this case
  // setting |include_parent_name| to false allows to exclude this information
  // from the formatted name.
  bool include_parent_name = true;

  NameFormattingParams(Object::NameVisibility visibility,
                       Object::NameDisambiguation name_disambiguation =
                           Object::NameDisambiguation::kNo)
      : name_visibility(visibility),
        disambiguate_names(name_disambiguation ==
                           Object::NameDisambiguation::kYes) {}

  static NameFormattingParams DisambiguatedWithoutClassName(
      Object::NameVisibility visibility) {
    NameFormattingParams params(visibility, Object::NameDisambiguation::kYes);
    params.include_class_name = false;
    return params;
  }

  static NameFormattingParams DisambiguatedUnqualified(
      Object::NameVisibility visibility) {
    NameFormattingParams params(visibility, Object::NameDisambiguation::kYes);
    params.include_class_name = false;
    params.include_parent_name = false;
    return params;
  }
};

class Function : public Object {
 public:
  StringPtr name() const { return untag()->name(); }
  StringPtr UserVisibleName() const;  // Same as scrubbed name.
  const char* UserVisibleNameCString() const;

  const char* NameCString(NameVisibility name_visibility) const;

  void PrintName(const NameFormattingParams& params,
                 BaseTextBuffer* printer) const;
  StringPtr QualifiedScrubbedName() const;
  const char* QualifiedScrubbedNameCString() const;
  StringPtr QualifiedUserVisibleName() const;
  const char* QualifiedUserVisibleNameCString() const;

  virtual StringPtr DictionaryName() const { return name(); }

  StringPtr GetSource() const;

  // Set the "C signature" for an FFI trampoline.
  // Can only be used on FFI trampolines.
  void SetFfiCSignature(const FunctionType& sig) const;

  // Retrieves the "C signature" for an FFI trampoline.
  // Can only be used on FFI trampolines.
  FunctionTypePtr FfiCSignature() const;

  bool FfiCSignatureContainsHandles() const;
  bool FfiCSignatureReturnsStruct() const;

  // Can only be called on FFI trampolines.
  // -1 for Dart -> native calls.
  int32_t FfiCallbackId() const;

  // Can only be called on FFI trampolines.
  void SetFfiCallbackId(int32_t value) const;

  // Can only be called on FFI trampolines.
  bool FfiIsLeaf() const;

  // Can only be called on FFI trampolines.
  void SetFfiIsLeaf(bool is_leaf) const;

  // Can only be called on FFI trampolines.
  // Null for Dart -> native calls.
  FunctionPtr FfiCallbackTarget() const;

  // Can only be called on FFI trampolines.
  void SetFfiCallbackTarget(const Function& target) const;

  // Can only be called on FFI trampolines.
  // Null for Dart -> native calls.
  InstancePtr FfiCallbackExceptionalReturn() const;

  // Can only be called on FFI trampolines.
  void SetFfiCallbackExceptionalReturn(const Instance& value) const;

  // Return the signature of this function.
  PRECOMPILER_WSR_FIELD_DECLARATION(FunctionType, signature);
  void SetSignature(const FunctionType& value) const;
  static intptr_t signature_offset() {
    return OFFSET_OF(UntaggedFunction, signature_);
  }

  // Build a string of the form '<T>(T, {B b, C c}) => R' representing the
  // internal signature of the given function. In this example, T is a type
  // parameter of this function and R is a type parameter of class C, the owner
  // of the function. B and C are not type parameters.
  StringPtr InternalSignature() const;

  // Build a string of the form '<T>(T, {B b, C c}) => R' representing the
  // user visible signature of the given function. In this example, T is a type
  // parameter of this function and R is a type parameter of class C, the owner
  // of the function. B and C are not type parameters.
  // Implicit parameters are hidden.
  StringPtr UserVisibleSignature() const;

  // Returns true if the signature of this function is instantiated, i.e. if it
  // does not involve generic parameter types or generic result type.
  // Note that function type parameters declared by this function do not make
  // its signature uninstantiated, only type parameters declared by parent
  // generic functions or class type parameters.
  bool HasInstantiatedSignature(Genericity genericity = kAny,
                                intptr_t num_free_fun_type_params = kAllFree,
                                TrailPtr trail = nullptr) const;

  bool IsPrivate() const;

  ClassPtr Owner() const;
  void set_owner(const Object& value) const;
  ClassPtr origin() const;
  ScriptPtr script() const;
  ObjectPtr RawOwner() const { return untag()->owner(); }

  // The NNBD mode of the library declaring this function.
  // TODO(alexmarkov): nnbd_mode() doesn't work for mixins.
  // It should be either removed or fixed.
  NNBDMode nnbd_mode() const { return Class::Handle(origin()).nnbd_mode(); }

  RegExpPtr regexp() const;
  intptr_t string_specialization_cid() const;
  bool is_sticky_specialization() const;
  void SetRegExpData(const RegExp& regexp,
                     intptr_t string_specialization_cid,
                     bool sticky) const;

  StringPtr native_name() const;
  void set_native_name(const String& name) const;

  AbstractTypePtr result_type() const {
    return signature()->untag()->result_type();
  }

  // The parameters, starting with NumImplicitParameters() parameters which are
  // only visible to the VM, but not to Dart users.
  // Note that type checks exclude implicit parameters.
  AbstractTypePtr ParameterTypeAt(intptr_t index) const;
  ArrayPtr parameter_types() const {
    return signature()->untag()->parameter_types();
  }

  // Outside of the AOT runtime, functions store the names for their positional
  // parameters, and delegate storage of the names for named parameters to
  // their signature. These methods handle fetching the name from and
  // setting the name to the correct location.
  StringPtr ParameterNameAt(intptr_t index) const;
  // Only valid for positional parameter indexes, as this should be called
  // explicitly on the signature for named parameters.
  void SetParameterNameAt(intptr_t index, const String& value) const;
  // Creates an appropriately sized array in the function to hold positional
  // parameter names, using the positional parameter count in the signature.
  // Uses same default space as Function::New.
  void CreateNameArray(Heap::Space space = Heap::kOld) const;

  // Delegates to the signature, which stores the named parameter flags.
  bool IsRequiredAt(intptr_t index) const;

  // The formal type parameters, their bounds, and defaults, are specified as an
  // object of type TypeParameters stored in the signature.
  TypeParametersPtr type_parameters() const {
    return signature()->untag()->type_parameters();
  }

  // Returns the number of local type arguments for this function.
  intptr_t NumTypeParameters() const;
  // Return the cumulative number of type arguments in all parent functions.
  intptr_t NumParentTypeArguments() const;
  // Return the cumulative number of type arguments for this function, including
  // type arguments for all parent functions.
  intptr_t NumTypeArguments() const;
  // Return whether this function declares local type arguments.
  bool IsGeneric() const;
  // Returns whether any parent function of this function is generic.
  bool HasGenericParent() const { return NumParentTypeArguments() > 0; }

  // Return the type parameter declared at index.
  TypeParameterPtr TypeParameterAt(
      intptr_t index,
      Nullability nullability = Nullability::kNonNullable) const;

  // Not thread-safe; must be called in the main thread.
  // Sets function's code and code's function.
  void InstallOptimizedCode(const Code& code) const;
  void AttachCode(const Code& value) const;
  void SetInstructions(const Code& value) const;
  void SetInstructionsSafe(const Code& value) const;
  void ClearCode() const;
  void ClearCodeSafe() const;

  // Disables optimized code and switches to unoptimized code.
  void SwitchToUnoptimizedCode() const;

  // Ensures that the function has code. If there is no code it compiles the
  // unoptimized version of the code.  If the code contains errors, it calls
  // Exceptions::PropagateError and does not return.  Normally returns the
  // current code, whether it is optimized or unoptimized.
  CodePtr EnsureHasCode() const;

  // Disables optimized code and switches to unoptimized code (or the lazy
  // compilation stub).
  void SwitchToLazyCompiledUnoptimizedCode() const;

  // Compiles unoptimized code (if necessary) and attaches it to the function.
  void EnsureHasCompiledUnoptimizedCode() const;

  // Return the most recently compiled and installed code for this function.
  // It is not the only Code object that points to this function.
  CodePtr CurrentCode() const { return CurrentCodeOf(ptr()); }

  bool SafeToClosurize() const;

  static CodePtr CurrentCodeOf(const FunctionPtr function) {
    return function->untag()->code();
  }

  CodePtr unoptimized_code() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    return static_cast<CodePtr>(Object::null());
#else
    return untag()->unoptimized_code();
#endif
  }
  void set_unoptimized_code(const Code& value) const;
  bool HasCode() const;
  static bool HasCode(FunctionPtr function);

  static intptr_t code_offset() { return OFFSET_OF(UntaggedFunction, code_); }

  uword entry_point() const { return untag()->entry_point_; }

  static intptr_t entry_point_offset(
      CodeEntryKind entry_kind = CodeEntryKind::kNormal) {
    switch (entry_kind) {
      case CodeEntryKind::kNormal:
        return OFFSET_OF(UntaggedFunction, entry_point_);
      case CodeEntryKind::kUnchecked:
        return OFFSET_OF(UntaggedFunction, unchecked_entry_point_);
      default:
        UNREACHABLE();
    }
  }

  static intptr_t unchecked_entry_point_offset() {
    return OFFSET_OF(UntaggedFunction, unchecked_entry_point_);
  }

  virtual uword Hash() const;

  // Returns true if there is at least one debugger breakpoint
  // set in this function.
  bool HasBreakpoint() const;

  ContextScopePtr context_scope() const;
  void set_context_scope(const ContextScope& value) const;

  // Enclosing function of this local function.
  FunctionPtr parent_function() const;

  using DefaultTypeArgumentsKind =
      UntaggedClosureData::DefaultTypeArgumentsKind;

  // Returns a canonicalized vector of the type parameters instantiated
  // to bounds. If non-generic, the empty type arguments vector is returned.
  TypeArgumentsPtr InstantiateToBounds(
      Thread* thread,
      DefaultTypeArgumentsKind* kind_out = nullptr) const;

  // Only usable for closure functions.
  DefaultTypeArgumentsKind default_type_arguments_kind() const;
  void set_default_type_arguments_kind(DefaultTypeArgumentsKind value) const;

  // Enclosing outermost function of this local function.
  FunctionPtr GetOutermostFunction() const;

  void set_extracted_method_closure(const Function& function) const;
  FunctionPtr extracted_method_closure() const;

  void set_saved_args_desc(const Array& array) const;
  ArrayPtr saved_args_desc() const;

  bool HasSavedArgumentsDescriptor() const {
    return IsInvokeFieldDispatcher() || IsNoSuchMethodDispatcher();
  }

  void set_accessor_field(const Field& value) const;
  FieldPtr accessor_field() const;

  bool IsRegularFunction() const {
    return kind() == UntaggedFunction::kRegularFunction;
  }

  bool IsMethodExtractor() const {
    return kind() == UntaggedFunction::kMethodExtractor;
  }

  bool IsNoSuchMethodDispatcher() const {
    return kind() == UntaggedFunction::kNoSuchMethodDispatcher;
  }

  bool IsInvokeFieldDispatcher() const {
    return kind() == UntaggedFunction::kInvokeFieldDispatcher;
  }

  bool IsDynamicInvokeFieldDispatcher() const {
    return IsInvokeFieldDispatcher() &&
           IsDynamicInvocationForwarderName(name());
  }

  // Performs all the checks that don't require the current thread first, to
  // avoid retrieving it unless they all pass. If you have a handle on the
  // current thread, call the version that takes one instead.
  bool IsDynamicClosureCallDispatcher() const {
    if (!IsDynamicInvokeFieldDispatcher()) return false;
    return IsDynamicClosureCallDispatcher(Thread::Current());
  }
  bool IsDynamicClosureCallDispatcher(Thread* thread) const;

  bool IsDynamicInvocationForwarder() const {
    return kind() == UntaggedFunction::kDynamicInvocationForwarder;
  }

  bool IsImplicitGetterOrSetter() const {
    return kind() == UntaggedFunction::kImplicitGetter ||
           kind() == UntaggedFunction::kImplicitSetter ||
           kind() == UntaggedFunction::kImplicitStaticGetter;
  }

  // Returns true iff an implicit closure function has been created
  // for this function.
  bool HasImplicitClosureFunction() const {
    return implicit_closure_function() != null();
  }

  // Returns the closure function implicitly created for this function.  If none
  // exists yet, create one and remember it.  Implicit closure functions are
  // used in VM Closure instances that represent results of tear-off operations.
  FunctionPtr ImplicitClosureFunction() const;
  void DropUncompiledImplicitClosureFunction() const;

  // Return the closure implicitly created for this function.
  // If none exists yet, create one and remember it.
  ClosurePtr ImplicitStaticClosure() const;

  ClosurePtr ImplicitInstanceClosure(const Instance& receiver) const;

  // Returns the target of the implicit closure or null if the target is now
  // invalid (e.g., mismatched argument shapes after a reload).
  FunctionPtr ImplicitClosureTarget(Zone* zone) const;

  FunctionPtr ForwardingTarget() const;
  void SetForwardingTarget(const Function& target) const;

  UntaggedFunction::Kind kind() const {
    return untag()->kind_tag_.Read<KindBits>();
  }

  UntaggedFunction::AsyncModifier modifier() const {
    return untag()->kind_tag_.Read<ModifierBits>();
  }

  static const char* KindToCString(UntaggedFunction::Kind kind);

  bool IsConstructor() const {
    return kind() == UntaggedFunction::kConstructor;
  }
  bool IsGenerativeConstructor() const {
    return IsConstructor() && !is_static();
  }
  bool IsImplicitConstructor() const;
  bool IsFactory() const { return IsConstructor() && is_static(); }

  bool HasThisParameter() const {
    return IsDynamicFunction(/*allow_abstract=*/true) ||
           IsGenerativeConstructor() || (IsFieldInitializer() && !is_static());
  }

  bool IsDynamicFunction(bool allow_abstract = false) const {
    if (is_static() || (!allow_abstract && is_abstract())) {
      return false;
    }
    switch (kind()) {
      case UntaggedFunction::kRegularFunction:
      case UntaggedFunction::kGetterFunction:
      case UntaggedFunction::kSetterFunction:
      case UntaggedFunction::kImplicitGetter:
      case UntaggedFunction::kImplicitSetter:
      case UntaggedFunction::kMethodExtractor:
      case UntaggedFunction::kNoSuchMethodDispatcher:
      case UntaggedFunction::kInvokeFieldDispatcher:
      case UntaggedFunction::kDynamicInvocationForwarder:
        return true;
      case UntaggedFunction::kClosureFunction:
      case UntaggedFunction::kImplicitClosureFunction:
      case UntaggedFunction::kConstructor:
      case UntaggedFunction::kImplicitStaticGetter:
      case UntaggedFunction::kFieldInitializer:
      case UntaggedFunction::kIrregexpFunction:
        return false;
      default:
        UNREACHABLE();
        return false;
    }
  }
  bool IsStaticFunction() const {
    if (!is_static()) {
      return false;
    }
    switch (kind()) {
      case UntaggedFunction::kRegularFunction:
      case UntaggedFunction::kGetterFunction:
      case UntaggedFunction::kSetterFunction:
      case UntaggedFunction::kImplicitGetter:
      case UntaggedFunction::kImplicitSetter:
      case UntaggedFunction::kImplicitStaticGetter:
      case UntaggedFunction::kFieldInitializer:
      case UntaggedFunction::kIrregexpFunction:
        return true;
      case UntaggedFunction::kClosureFunction:
      case UntaggedFunction::kImplicitClosureFunction:
      case UntaggedFunction::kConstructor:
      case UntaggedFunction::kMethodExtractor:
      case UntaggedFunction::kNoSuchMethodDispatcher:
      case UntaggedFunction::kInvokeFieldDispatcher:
      case UntaggedFunction::kDynamicInvocationForwarder:
        return false;
      default:
        UNREACHABLE();
        return false;
    }
  }

  bool NeedsTypeArgumentTypeChecks() const {
    return !(is_static() || (kind() == UntaggedFunction::kConstructor));
  }

  bool NeedsArgumentTypeChecks() const {
    return !(is_static() || (kind() == UntaggedFunction::kConstructor));
  }

  bool NeedsMonomorphicCheckedEntry(Zone* zone) const;
  bool HasDynamicCallers(Zone* zone) const;
  bool PrologueNeedsArgumentsDescriptor() const;

  bool MayHaveUncheckedEntryPoint() const;

  TokenPosition token_pos() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    return TokenPosition::kNoSource;
#else
    return untag()->token_pos_;
#endif
  }
  void set_token_pos(TokenPosition value) const;

  TokenPosition end_token_pos() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    return TokenPosition::kNoSource;
#else
    return untag()->end_token_pos_;
#endif
  }
  void set_end_token_pos(TokenPosition value) const {
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
#else
    StoreNonPointer(&untag()->end_token_pos_, value);
#endif
  }

  // Returns the size of the source for this function.
  intptr_t SourceSize() const;

  uint32_t packed_fields() const { return untag()->packed_fields_; }
  void set_packed_fields(uint32_t packed_fields) const;
  static intptr_t packed_fields_offset() {
    return OFFSET_OF(UntaggedFunction, packed_fields_);
  }

  // Returns the number of required positional parameters.
  intptr_t num_fixed_parameters() const;
  // Returns the number of optional parameters, whether positional or named.
  bool HasOptionalParameters() const;
  // Returns whether the function has optional named parameters.
  bool HasOptionalNamedParameters() const;
  // Returns whether the fuction has required named parameters.
  bool HasRequiredNamedParameters() const;
  // Returns whether the function has optional positional parameters.
  bool HasOptionalPositionalParameters() const;
  // Returns the number of optional parameters, or 0 if none.
  intptr_t NumOptionalParameters() const;
  // Returns the number of optional positional parameters, or 0 if none.
  intptr_t NumOptionalPositionalParameters() const;
  // Returns the number of optional named parameters, or 0 if none.
  intptr_t NumOptionalNamedParameters() const;
  // Returns the total number of both required and optional parameters.
  intptr_t NumParameters() const;
  // Returns the number of implicit parameters, e.g., this for instance methods.
  intptr_t NumImplicitParameters() const;

#if defined(DART_PRECOMPILED_RUNTIME)
#define DEFINE_GETTERS_AND_SETTERS(return_type, type, name)                    \
  static intptr_t name##_offset() {                                            \
    UNREACHABLE();                                                             \
    return 0;                                                                  \
  }                                                                            \
  return_type name() const { return 0; }                                       \
                                                                               \
  void set_##name(type value) const { UNREACHABLE(); }
#else
#define DEFINE_GETTERS_AND_SETTERS(return_type, type, name)                    \
  static intptr_t name##_offset() {                                            \
    return OFFSET_OF(UntaggedFunction, name##_);                               \
  }                                                                            \
  return_type name() const {                                                   \
    return LoadNonPointer<type, std::memory_order_relaxed>(&untag()->name##_); \
  }                                                                            \
                                                                               \
  void set_##name(type value) const {                                          \
    StoreNonPointer<type, type, std::memory_order_relaxed>(&untag()->name##_,  \
                                                           value);             \
  }
#endif

  JIT_FUNCTION_COUNTERS(DEFINE_GETTERS_AND_SETTERS)

#undef DEFINE_GETTERS_AND_SETTERS

  intptr_t kernel_offset() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    return 0;
#else
    return untag()->kernel_offset_;
#endif
  }

  void set_kernel_offset(intptr_t value) const {
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
#else
    ASSERT(value >= 0);
    StoreNonPointer(&untag()->kernel_offset_, value);
#endif
  }

  void InheritKernelOffsetFrom(const Function& src) const;
  void InheritKernelOffsetFrom(const Field& src) const;

  static const intptr_t kMaxInstructionCount = (1 << 16) - 1;

  void SetOptimizedInstructionCountClamped(uintptr_t value) const {
    if (value > kMaxInstructionCount) value = kMaxInstructionCount;
    set_optimized_instruction_count(value);
  }

  void SetOptimizedCallSiteCountClamped(uintptr_t value) const {
    if (value > kMaxInstructionCount) value = kMaxInstructionCount;
    set_optimized_call_site_count(value);
  }

  void SetKernelDataAndScript(const Script& script,
                              const ExternalTypedData& data,
                              intptr_t offset) const;

  intptr_t KernelDataProgramOffset() const;

  ExternalTypedDataPtr KernelData() const;

  bool IsOptimizable() const;
  void SetIsOptimizable(bool value) const;

  // Whether this function must be optimized immediately and cannot be compiled
  // with the unoptimizing compiler. Such a function must be sure to not
  // deoptimize, since we won't generate deoptimization info or register
  // dependencies. It will be compiled into optimized code immediately when it's
  // run.
  bool ForceOptimize() const;

  bool IsFinalizerForceOptimized() const;

  bool CanBeInlined() const;

  MethodRecognizer::Kind recognized_kind() const {
    return untag()->kind_tag_.Read<RecognizedBits>();
  }
  void set_recognized_kind(MethodRecognizer::Kind value) const;

  bool IsRecognized() const {
    return recognized_kind() != MethodRecognizer::kUnknown;
  }

  bool HasOptimizedCode() const;

  // Returns true if the argument counts are valid for calling this function.
  // Otherwise, it returns false and the reason (if error_message is not NULL).
  bool AreValidArgumentCounts(intptr_t num_type_arguments,
                              intptr_t num_arguments,
                              intptr_t num_named_arguments,
                              String* error_message) const;

  // Returns a TypeError if the provided arguments don't match the function
  // parameter types, null otherwise. Assumes AreValidArguments is called first.
  //
  // If the function has a non-null receiver in the arguments, the instantiator
  // type arguments are retrieved from the receiver, otherwise the null type
  // arguments vector is used.
  //
  // If the function is generic, the appropriate function type arguments are
  // retrieved either from the arguments array or the receiver (if a closure).
  // If no function type arguments are available in either location, the bounds
  // of the function type parameters are instantiated and used as the function
  // type arguments.
  //
  // The local function type arguments (_not_ parent function type arguments)
  // are also checked against the bounds of the corresponding parameters to
  // ensure they are appropriate subtypes if the function is generic.
  ObjectPtr DoArgumentTypesMatch(const Array& args,
                                 const ArgumentsDescriptor& arg_names) const;

  // Returns a TypeError if the provided arguments don't match the function
  // parameter types, null otherwise. Assumes AreValidArguments is called first.
  //
  // If the function is generic, the appropriate function type arguments are
  // retrieved either from the arguments array or the receiver (if a closure).
  // If no function type arguments are available in either location, the bounds
  // of the function type parameters are instantiated and used as the function
  // type arguments.
  //
  // The local function type arguments (_not_ parent function type arguments)
  // are also checked against the bounds of the corresponding parameters to
  // ensure they are appropriate subtypes if the function is generic.
  ObjectPtr DoArgumentTypesMatch(
      const Array& args,
      const ArgumentsDescriptor& arg_names,
      const TypeArguments& instantiator_type_args) const;

  // Returns a TypeError if the provided arguments don't match the function
  // parameter types, null otherwise. Assumes AreValidArguments is called first.
  //
  // The local function type arguments (_not_ parent function type arguments)
  // are also checked against the bounds of the corresponding parameters to
  // ensure they are appropriate subtypes if the function is generic.
  ObjectPtr DoArgumentTypesMatch(const Array& args,
                                 const ArgumentsDescriptor& arg_names,
                                 const TypeArguments& instantiator_type_args,
                                 const TypeArguments& function_type_args) const;

  // Returns true if the type argument count, total argument count and the names
  // of optional arguments are valid for calling this function.
  // Otherwise, it returns false and the reason (if error_message is not NULL).
  bool AreValidArguments(intptr_t num_type_arguments,
                         intptr_t num_arguments,
                         const Array& argument_names,
                         String* error_message) const;
  bool AreValidArguments(const ArgumentsDescriptor& args_desc,
                         String* error_message) const;

  // Fully qualified name uniquely identifying the function under gdb and during
  // ast printing. The special ':' character, if present, is replaced by '_'.
  const char* ToFullyQualifiedCString() const;

  const char* ToLibNamePrefixedQualifiedCString() const;

  const char* ToQualifiedCString() const;

  static constexpr intptr_t maximum_unboxed_parameter_count() {
    // Subtracts one that represents the return value
    return UntaggedFunction::UnboxedParameterBitmap::kCapacity - 1;
  }

  void reset_unboxed_parameters_and_return() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
    StoreNonPointer(&untag()->unboxed_parameters_info_,
                    UntaggedFunction::UnboxedParameterBitmap());
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)
  }

  void set_unboxed_integer_parameter_at(intptr_t index) const {
#if !defined(DART_PRECOMPILED_RUNTIME)
    ASSERT(index >= 0 && index < maximum_unboxed_parameter_count());
    index++;  // position 0 is reserved for the return value
    const_cast<UntaggedFunction::UnboxedParameterBitmap*>(
        &untag()->unboxed_parameters_info_)
        ->SetUnboxedInteger(index);
#else
    UNREACHABLE();
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)
  }

  void set_unboxed_double_parameter_at(intptr_t index) const {
#if !defined(DART_PRECOMPILED_RUNTIME)
    ASSERT(index >= 0 && index < maximum_unboxed_parameter_count());
    index++;  // position 0 is reserved for the return value
    const_cast<UntaggedFunction::UnboxedParameterBitmap*>(
        &untag()->unboxed_parameters_info_)
        ->SetUnboxedDouble(index);

#else
    UNREACHABLE();
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)
  }

  void set_unboxed_integer_return() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
    const_cast<UntaggedFunction::UnboxedParameterBitmap*>(
        &untag()->unboxed_parameters_info_)
        ->SetUnboxedInteger(0);
#else
    UNREACHABLE();
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)
  }

  void set_unboxed_double_return() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
    const_cast<UntaggedFunction::UnboxedParameterBitmap*>(
        &untag()->unboxed_parameters_info_)
        ->SetUnboxedDouble(0);

#else
    UNREACHABLE();
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)
  }

  bool is_unboxed_parameter_at(intptr_t index) const {
#if !defined(DART_PRECOMPILED_RUNTIME)
    ASSERT(index >= 0);
    index++;  // position 0 is reserved for the return value
    return untag()->unboxed_parameters_info_.IsUnboxed(index);
#else
    return false;
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)
  }

  bool is_unboxed_integer_parameter_at(intptr_t index) const {
#if !defined(DART_PRECOMPILED_RUNTIME)
    ASSERT(index >= 0);
    index++;  // position 0 is reserved for the return value
    return untag()->unboxed_parameters_info_.IsUnboxedInteger(index);
#else
    return false;
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)
  }

  bool is_unboxed_double_parameter_at(intptr_t index) const {
#if !defined(DART_PRECOMPILED_RUNTIME)
    ASSERT(index >= 0);
    index++;  // position 0 is reserved for the return value
    return untag()->unboxed_parameters_info_.IsUnboxedDouble(index);
#else
    return false;
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)
  }

  bool has_unboxed_return() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
    return untag()->unboxed_parameters_info_.IsUnboxed(0);
#else
    return false;
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)
  }

  bool has_unboxed_integer_return() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
    return untag()->unboxed_parameters_info_.IsUnboxedInteger(0);
#else
    return false;
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)
  }

  bool has_unboxed_double_return() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
    return untag()->unboxed_parameters_info_.IsUnboxedDouble(0);
#else
    return false;
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)
  }

#if !defined(DART_PRECOMPILED_RUNTIME)
  bool HasUnboxedParameters() const {
    return untag()->unboxed_parameters_info_.HasUnboxedParameters();
  }
  bool HasUnboxedReturnValue() const {
    return untag()->unboxed_parameters_info_.HasUnboxedReturnValue();
  }
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)

  bool IsDispatcherOrImplicitAccessor() const {
    switch (kind()) {
      case UntaggedFunction::kImplicitGetter:
      case UntaggedFunction::kImplicitSetter:
      case UntaggedFunction::kImplicitStaticGetter:
      case UntaggedFunction::kNoSuchMethodDispatcher:
      case UntaggedFunction::kInvokeFieldDispatcher:
      case UntaggedFunction::kDynamicInvocationForwarder:
        return true;
      default:
        return false;
    }
  }

  // Returns true if this function represents an explicit getter function.
  bool IsGetterFunction() const {
    return kind() == UntaggedFunction::kGetterFunction;
  }

  // Returns true if this function represents an implicit getter function.
  bool IsImplicitGetterFunction() const {
    return kind() == UntaggedFunction::kImplicitGetter;
  }

  // Returns true if this function represents an implicit static getter
  // function.
  bool IsImplicitStaticGetterFunction() const {
    return kind() == UntaggedFunction::kImplicitStaticGetter;
  }

  // Returns true if this function represents an explicit setter function.
  bool IsSetterFunction() const {
    return kind() == UntaggedFunction::kSetterFunction;
  }

  // Returns true if this function represents an implicit setter function.
  bool IsImplicitSetterFunction() const {
    return kind() == UntaggedFunction::kImplicitSetter;
  }

  // Returns true if this function represents an initializer for a static or
  // instance field. The function returns the initial value and the caller is
  // responsible for setting the field.
  bool IsFieldInitializer() const {
    return kind() == UntaggedFunction::kFieldInitializer;
  }

  // Returns true if this function represents a (possibly implicit) closure
  // function.
  bool IsClosureFunction() const {
    UntaggedFunction::Kind k = kind();
    return (k == UntaggedFunction::kClosureFunction) ||
           (k == UntaggedFunction::kImplicitClosureFunction);
  }

  // Returns true if this function represents a generated irregexp function.
  bool IsIrregexpFunction() const {
    return kind() == UntaggedFunction::kIrregexpFunction;
  }

  // Returns true if this function represents an implicit closure function.
  bool IsImplicitClosureFunction() const {
    return kind() == UntaggedFunction::kImplicitClosureFunction;
  }

  // Returns true if this function represents a non implicit closure function.
  bool IsNonImplicitClosureFunction() const {
    return IsClosureFunction() && !IsImplicitClosureFunction();
  }

  // Returns true if this function represents an implicit static closure
  // function.
  bool IsImplicitStaticClosureFunction() const {
    return IsImplicitClosureFunction() && is_static();
  }
  static bool IsImplicitStaticClosureFunction(FunctionPtr func);

  // Returns true if this function represents an implicit instance closure
  // function.
  bool IsImplicitInstanceClosureFunction() const {
    return IsImplicitClosureFunction() && !is_static();
  }

  // Returns true if this function has a parent function.
  bool HasParent() const { return parent_function() != Function::null(); }

  // Returns true if this function is a local function.
  bool IsLocalFunction() const {
    return !IsImplicitClosureFunction() && HasParent();
  }

  // Returns true if this function represents an ffi trampoline.
  bool IsFfiTrampoline() const {
    return kind() == UntaggedFunction::kFfiTrampoline;
  }
  static bool IsFfiTrampoline(FunctionPtr function) {
    NoSafepointScope no_safepoint;
    return function->untag()->kind_tag_.Read<KindBits>() ==
           UntaggedFunction::kFfiTrampoline;
  }

  bool IsFfiLoad() const {
    const auto kind = recognized_kind();
    return MethodRecognizer::kFfiLoadInt8 <= kind &&
           kind <= MethodRecognizer::kFfiLoadPointer;
  }

  bool IsFfiStore() const {
    const auto kind = recognized_kind();
    return MethodRecognizer::kFfiStoreInt8 <= kind &&
           kind <= MethodRecognizer::kFfiStorePointer;
  }

  bool IsFfiFromAddress() const {
    const auto kind = recognized_kind();
    return kind == MethodRecognizer::kFfiFromAddress;
  }

  bool IsFfiGetAddress() const {
    const auto kind = recognized_kind();
    return kind == MethodRecognizer::kFfiGetAddress;
  }

  bool IsFfiAsExternalTypedData() const {
    const auto kind = recognized_kind();
    return MethodRecognizer::kFfiAsExternalTypedDataInt8 <= kind &&
           kind <= MethodRecognizer::kFfiAsExternalTypedDataDouble;
  }

  bool IsGetNativeField() const {
    const auto kind = recognized_kind();
    return kind == MethodRecognizer::kGetNativeField;
  }

  bool IsUtf8Scan() const {
    const auto kind = recognized_kind();
    return kind == MethodRecognizer::kUtf8DecoderScan;
  }

  // Recognise async functions like:
  //   user_func async {
  //     // ...
  //   }
  bool IsAsyncFunction() const {
    return modifier() == UntaggedFunction::kAsync;
  }

  // Recognise synthetic sync-yielding functions like the inner-most:
  //   user_func /* was async */ {
  //      :async_op(..) yielding {
  //        // ...
  //      }
  //   }
  bool IsAsyncClosure() const {
    return is_generated_body() &&
           Function::Handle(parent_function()).IsAsyncFunction();
  }

  // Recognise sync* functions like:
  //   user_func sync* {
  //     // ...
  //   }
  bool IsSyncGenerator() const {
    return modifier() == UntaggedFunction::kSyncGen;
  }

  // Recognise synthetic :sync_op_gen()s like:
  //   user_func /* was sync* */ {
  //     :sync_op_gen() {
  //        // ...
  //      }
  //   }
  bool IsSyncGenClosureMaker() const {
    return is_generated_body() &&
           Function::Handle(parent_function()).IsSyncGenerator();
  }

  // Recognise async* functions like:
  //   user_func async* {
  //     // ...
  //   }
  bool IsAsyncGenerator() const {
    return modifier() == UntaggedFunction::kAsyncGen;
  }

  // Recognise synthetic sync-yielding functions like the inner-most:
  //   user_func /* originally async* */ {
  //      :async_op(..) yielding {
  //        // ...
  //      }
  //   }
  bool IsAsyncGenClosure() const {
    return is_generated_body() &&
           Function::Handle(parent_function()).IsAsyncGenerator();
  }

  bool IsAsyncOrGenerator() const {
    return modifier() != UntaggedFunction::kNoModifier;
  }

  // Recognise synthetic sync-yielding functions like the inner-most:
  //   user_func /* was sync* */ {
  //     :sync_op_gen() {
  //        :sync_op(..) yielding {
  //          // ...
  //        }
  //      }
  //   }
  bool IsSyncGenClosure() const {
    return is_generated_body() &&
           Function::Handle(parent_function()).IsSyncGenClosureMaker();
  }

  bool IsTypedDataViewFactory() const {
    if (is_native() && kind() == UntaggedFunction::kConstructor) {
      // This is a native factory constructor.
      const Class& klass = Class::Handle(Owner());
      return IsTypedDataViewClassId(klass.id());
    }
    return false;
  }

  DART_WARN_UNUSED_RESULT
  ErrorPtr VerifyCallEntryPoint() const;

  DART_WARN_UNUSED_RESULT
  ErrorPtr VerifyClosurizedEntryPoint() const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedFunction));
  }

  static FunctionPtr 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 = Heap::kOld);

  // Allocates a new Function object representing a closure function
  // with given kind - kClosureFunction or kImplicitClosureFunction.
  static FunctionPtr NewClosureFunctionWithKind(UntaggedFunction::Kind kind,
                                                const String& name,
                                                const Function& parent,
                                                bool is_static,
                                                TokenPosition token_pos,
                                                const Object& owner);

  // Allocates a new Function object representing a closure function.
  static FunctionPtr NewClosureFunction(const String& name,
                                        const Function& parent,
                                        TokenPosition token_pos);

  // Allocates a new Function object representing an implicit closure function.
  static FunctionPtr NewImplicitClosureFunction(const String& name,
                                                const Function& parent,
                                                TokenPosition token_pos);

  FunctionPtr CreateMethodExtractor(const String& getter_name) const;
  FunctionPtr GetMethodExtractor(const String& getter_name) const;

  static bool IsDynamicInvocationForwarderName(const String& name);
  static bool IsDynamicInvocationForwarderName(StringPtr name);

  static StringPtr DemangleDynamicInvocationForwarderName(const String& name);

  static StringPtr CreateDynamicInvocationForwarderName(const String& name);

#if !defined(DART_PRECOMPILED_RUNTIME)
  FunctionPtr CreateDynamicInvocationForwarder(
      const String& mangled_name) const;

  FunctionPtr GetDynamicInvocationForwarder(const String& mangled_name,
                                            bool allow_add = true) const;
#endif

  // Slow function, use in asserts to track changes in important library
  // functions.
  int32_t SourceFingerprint() const;

  // Return false and report an error if the fingerprint does not match.
  bool CheckSourceFingerprint(int32_t fp, const char* kind = nullptr) const;

  // Works with map [deopt-id] -> ICData.
  void SaveICDataMap(
      const ZoneGrowableArray<const ICData*>& deopt_id_to_ic_data,
      const Array& edge_counters_array,
      const Array& coverage_array) const;
  // Uses 'ic_data_array' to populate the table 'deopt_id_to_ic_data'. Clone
  // ic_data (array and descriptor) if 'clone_ic_data' is true.
  void RestoreICDataMap(ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data,
                        bool clone_ic_data) const;

  // ic_data_array attached to the function stores edge counters in the
  // first element, coverage data array in the second element and the rest
  // are ICData objects.
  struct ICDataArrayIndices {
    static constexpr intptr_t kEdgeCounters = 0;
    static constexpr intptr_t kCoverageData = 1;
    static constexpr intptr_t kFirstICData = 2;
  };

  ArrayPtr ic_data_array() const;
  void ClearICDataArray() const;
  ICDataPtr FindICData(intptr_t deopt_id) const;

  // Coverage data array is a list of pairs:
  //   element 2 * i + 0 is token position
  //   element 2 * i + 1 is coverage hit (zero meaning code was not hit)
  ArrayPtr GetCoverageArray() const;

  // Outputs this function's service ID to the provided JSON object.
  void AddFunctionServiceId(const JSONObject& obj) const;

  // Sets deopt reason in all ICData-s with given deopt_id.
  void SetDeoptReasonForAll(intptr_t deopt_id, ICData::DeoptReasonId reason);

  void set_modifier(UntaggedFunction::AsyncModifier value) const;

// 'WasCompiled' is true if the function was compiled once in this
// VM instantiation. It is independent from presence of type feedback
// (ic_data_array) and code, which may be loaded from a snapshot.
// 'WasExecuted' is true if the usage counter has ever been positive.
// 'ProhibitsHoistingCheckClass' is true if this function deoptimized before on
// a hoisted check class instruction.
// 'ProhibitsBoundsCheckGeneralization' is true if this function deoptimized
// before on a generalized bounds check.
#define STATE_BITS_LIST(V)                                                     \
  V(WasCompiled)                                                               \
  V(WasExecutedBit)                                                            \
  V(ProhibitsHoistingCheckClass)                                               \
  V(ProhibitsBoundsCheckGeneralization)

  enum StateBits {
#define DECLARE_FLAG_POS(Name) k##Name##Pos,
    STATE_BITS_LIST(DECLARE_FLAG_POS)
#undef DECLARE_FLAG_POS
  };
#define DEFINE_FLAG_BIT(Name)                                                  \
  class Name##Bit : public BitField<uint8_t, bool, k##Name##Pos, 1> {};
  STATE_BITS_LIST(DEFINE_FLAG_BIT)
#undef DEFINE_FLAG_BIT

#define DEFINE_FLAG_ACCESSORS(Name)                                            \
  void Set##Name(bool value) const {                                           \
    set_state_bits(Name##Bit::update(value, state_bits()));                    \
  }                                                                            \
  bool Name() const { return Name##Bit::decode(state_bits()); }
  STATE_BITS_LIST(DEFINE_FLAG_ACCESSORS)
#undef DEFINE_FLAG_ACCESSORS

  void SetUsageCounter(intptr_t value) const {
    if (usage_counter() > 0) {
      SetWasExecuted(true);
    }
    set_usage_counter(value);
  }

  bool WasExecuted() const { return (usage_counter() > 0) || WasExecutedBit(); }

  void SetWasExecuted(bool value) const { SetWasExecutedBit(value); }

  static intptr_t data_offset() { return OFFSET_OF(UntaggedFunction, data_); }

  static intptr_t kind_tag_offset() {
    return OFFSET_OF(UntaggedFunction, kind_tag_);
  }

  // static: Considered during class-side or top-level resolution rather than
  //         instance-side resolution.
  // const: Valid target of a const constructor call.
  // abstract: Skipped during instance-side resolution.
  // reflectable: Enumerated by mirrors, invocable by mirrors. False for private
  //              functions of dart: libraries.
  // debuggable: Valid location of a breakpoint. Synthetic code is not
  //             debuggable.
  // visible: Frame is included in stack traces. Synthetic code such as
  //          dispatchers is not visible. Synthetic code that can trigger
  //          exceptions such as the outer async functions that create Futures
  //          is visible.
  // instrinsic: Has a hand-written assembly prologue.
  // inlinable: Candidate for inlining. False for functions with features we
  //            don't support during inlining (e.g., optional parameters),
  //            functions which are too big, etc.
  // native: Bridge to C/C++ code.
  // external: Just a declaration that expects to be defined in another patch
  //           file.
  // generated_body: Has a generated body.
  // polymorphic_target: A polymorphic method.
  // has_pragma: Has a @pragma decoration.
  // no_such_method_forwarder: A stub method that just calls noSuchMethod.

// Bits that are set when function is created, don't have to worry about
// concurrent updates.
#define FOR_EACH_FUNCTION_KIND_BIT(V)                                          \
  V(Static, is_static)                                                         \
  V(Const, is_const)                                                           \
  V(Abstract, is_abstract)                                                     \
  V(Reflectable, is_reflectable)                                               \
  V(Visible, is_visible)                                                       \
  V(Debuggable, is_debuggable)                                                 \
  V(Intrinsic, is_intrinsic)                                                   \
  V(Native, is_native)                                                         \
  V(External, is_external)                                                     \
  V(GeneratedBody, is_generated_body)                                          \
  V(PolymorphicTarget, is_polymorphic_target)                                  \
  V(HasPragma, has_pragma)                                                     \
  V(IsSynthetic, is_synthetic)                                                 \
  V(IsExtensionMember, is_extension_member)                                    \
  V(IsRedirectingFactory, is_redirecting_factory)
// Bit that is updated after function is constructed, has to be updated in
// concurrent-safe manner.
#define FOR_EACH_FUNCTION_VOLATILE_KIND_BIT(V) V(Inlinable, is_inlinable)

#define DEFINE_ACCESSORS(name, accessor_name)                                  \
  void set_##accessor_name(bool value) const {                                 \
    untag()->kind_tag_.UpdateUnsynchronized<name##Bit>(value);                 \
  }                                                                            \
  bool accessor_name() const { return untag()->kind_tag_.Read<name##Bit>(); }
  FOR_EACH_FUNCTION_KIND_BIT(DEFINE_ACCESSORS)
#undef DEFINE_ACCESSORS

#define DEFINE_ACCESSORS(name, accessor_name)                                  \
  void set_##accessor_name(bool value) const {                                 \
    untag()->kind_tag_.UpdateBool<name##Bit>(value);                           \
  }                                                                            \
  bool accessor_name() const { return untag()->kind_tag_.Read<name##Bit>(); }
  FOR_EACH_FUNCTION_VOLATILE_KIND_BIT(DEFINE_ACCESSORS)
#undef DEFINE_ACCESSORS

  // optimizable: Candidate for going through the optimizing compiler. False for
  //              some functions known to be execute infrequently and functions
  //              which have been de-optimized too many times.
  bool is_optimizable() const {
    return untag()->packed_fields_.Read<UntaggedFunction::PackedOptimizable>();
  }
  void set_is_optimizable(bool value) const {
    untag()->packed_fields_.UpdateBool<UntaggedFunction::PackedOptimizable>(
        value);
  }

  enum KindTagBits {
    kKindTagPos = 0,
    kKindTagSize = 5,
    kRecognizedTagPos = kKindTagPos + kKindTagSize,
    kRecognizedTagSize = 9,
    kModifierPos = kRecognizedTagPos + kRecognizedTagSize,
    kModifierSize = 2,
    kLastModifierBitPos = kModifierPos + (kModifierSize - 1),
// Single bit sized fields start here.
#define DECLARE_BIT(name, _) k##name##Bit,
    FOR_EACH_FUNCTION_KIND_BIT(DECLARE_BIT)
        FOR_EACH_FUNCTION_VOLATILE_KIND_BIT(DECLARE_BIT)
#undef DECLARE_BIT
            kNumTagBits
  };

  COMPILE_ASSERT(MethodRecognizer::kNumRecognizedMethods <
                 (1 << kRecognizedTagSize));
  COMPILE_ASSERT(kNumTagBits <=
                 (kBitsPerByte *
                  sizeof(decltype(UntaggedFunction::kind_tag_))));

  class KindBits : public BitField<uint32_t,
                                   UntaggedFunction::Kind,
                                   kKindTagPos,
                                   kKindTagSize> {};

  class RecognizedBits : public BitField<uint32_t,
                                         MethodRecognizer::Kind,
                                         kRecognizedTagPos,
                                         kRecognizedTagSize> {};
  class ModifierBits : public BitField<uint32_t,
                                       UntaggedFunction::AsyncModifier,
                                       kModifierPos,
                                       kModifierSize> {};

#define DEFINE_BIT(name, _)                                                    \
  class name##Bit : public BitField<uint32_t, bool, k##name##Bit, 1> {};
  FOR_EACH_FUNCTION_KIND_BIT(DEFINE_BIT)
  FOR_EACH_FUNCTION_VOLATILE_KIND_BIT(DEFINE_BIT)
#undef DEFINE_BIT

 private:
  // Given the provided defaults type arguments, determines which
  // DefaultTypeArgumentsKind applies.
  DefaultTypeArgumentsKind DefaultTypeArgumentsKindFor(
      const TypeArguments& defaults) const;

  void set_ic_data_array(const Array& value) const;
  void set_name(const String& value) const;
  void set_kind(UntaggedFunction::Kind value) const;
  void set_parent_function(const Function& value) const;
  FunctionPtr implicit_closure_function() const;
  void set_implicit_closure_function(const Function& value) const;
  ClosurePtr implicit_static_closure() const;
  void set_implicit_static_closure(const Closure& closure) const;
  ScriptPtr eval_script() const;
  void set_eval_script(const Script& value) const;
  void set_num_optional_parameters(intptr_t value) const;  // Encoded value.
  void set_kind_tag(uint32_t value) const;

#if !defined(DART_PRECOMPILED_RUNTIME)
  ArrayPtr positional_parameter_names() const {
    return untag()->positional_parameter_names();
  }
  void set_positional_parameter_names(const Array& value) const;
#endif

  ObjectPtr data() const { return untag()->data<std::memory_order_acquire>(); }
  void set_data(const Object& value) const;

  static FunctionPtr New(Heap::Space space = Heap::kOld);

  FINAL_HEAP_OBJECT_IMPLEMENTATION(Function, Object);
  friend class Class;
  friend class Parser;  // For set_eval_script.
  // UntaggedFunction::VisitFunctionPointers accesses the private constructor of
  // Function.
  friend class UntaggedFunction;
  friend class ClassFinalizer;  // To reset parent_function.
  friend class Type;            // To adjust parent_function.
  friend class Precompiler;     // To access closure data.
  friend class ProgramVisitor;  // For set_parameter_types/names.
};

class ClosureData : public Object {
 public:
  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedClosureData));
  }

  static intptr_t default_type_arguments_kind_offset() {
    return OFFSET_OF(UntaggedClosureData, default_type_arguments_kind_);
  }

  using DefaultTypeArgumentsKind =
      UntaggedClosureData::DefaultTypeArgumentsKind;

 private:
  ContextScopePtr context_scope() const { return untag()->context_scope(); }
  void set_context_scope(const ContextScope& value) const;

  // Enclosing function of this local function.
  PRECOMPILER_WSR_FIELD_DECLARATION(Function, parent_function)

  ClosurePtr implicit_static_closure() const {
    return untag()->closure<std::memory_order_acquire>();
  }
  void set_implicit_static_closure(const Closure& closure) const;

  DefaultTypeArgumentsKind default_type_arguments_kind() const;
  void set_default_type_arguments_kind(DefaultTypeArgumentsKind value) const;

  static ClosureDataPtr New();

  FINAL_HEAP_OBJECT_IMPLEMENTATION(ClosureData, Object);
  friend class Class;
  friend class Function;
  friend class Precompiler;  // To wrap parent functions in WSRs.
};

enum class EntryPointPragma {
  kAlways,
  kNever,
  kGetterOnly,
  kSetterOnly,
  kCallOnly
};

class FfiTrampolineData : public Object {
 public:
  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedFfiTrampolineData));
  }

 private:
  FunctionTypePtr c_signature() const { return untag()->c_signature(); }
  void set_c_signature(const FunctionType& value) const;

  FunctionPtr callback_target() const { return untag()->callback_target(); }
  void set_callback_target(const Function& value) const;

  InstancePtr callback_exceptional_return() const {
    return untag()->callback_exceptional_return();
  }
  void set_callback_exceptional_return(const Instance& value) const;

  int32_t callback_id() const { return untag()->callback_id_; }
  void set_callback_id(int32_t value) const;

  bool is_leaf() const { return untag()->is_leaf_; }
  void set_is_leaf(bool value) const;

  static FfiTrampolineDataPtr New();

  FINAL_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData, Object);
  friend class Class;
  friend class Function;
};

class Field : public Object {
 public:
  // The field that this field was cloned from, or this field itself if it isn't
  // a clone. The purpose of cloning is that the fields the background compiler
  // sees are consistent.
  FieldPtr Original() const;

  // Set the original field that this field was cloned from.
  void SetOriginal(const Field& value) const;

  // Returns whether this field is an original or a clone.
  bool IsOriginal() const {
    if (IsNull()) {
      return true;
    }
    NoSafepointScope no_safepoint;
    return !untag()->owner()->IsField();
  }

  // Mark previously unboxed field boxed. Only operates on clones, updates
  // original as well as this clone.
  void DisableFieldUnboxing() const;
  // Returns a field cloned from 'this'. 'this' is set as the
  // original field of result.
  FieldPtr CloneFromOriginal() const;

  StringPtr name() const { return untag()->name(); }
  StringPtr UserVisibleName() const;  // Same as scrubbed name.
  const char* UserVisibleNameCString() const;
  virtual StringPtr DictionaryName() const { return name(); }

  uint16_t kind_bits() const {
    return LoadNonPointer<uint16_t, std::memory_order_acquire>(
        &untag()->kind_bits_);
  }

  bool is_static() const { return StaticBit::decode(kind_bits()); }
  bool is_instance() const { return !is_static(); }
  bool is_final() const { return FinalBit::decode(kind_bits()); }
  bool is_const() const { return ConstBit::decode(kind_bits()); }
  bool is_late() const { return IsLateBit::decode(kind_bits()); }
  bool is_extension_member() const {
    return IsExtensionMemberBit::decode(kind_bits());
  }
  bool needs_load_guard() const {
    return NeedsLoadGuardBit::decode(kind_bits());
  }
  bool is_reflectable() const { return ReflectableBit::decode(kind_bits()); }
  void set_is_reflectable(bool value) const {
    ASSERT(IsOriginal());
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(ReflectableBit::update(value, untag()->kind_bits_));
  }
  bool is_double_initialized() const {
    return DoubleInitializedBit::decode(kind_bits());
  }
  // Called in parser after allocating field, immutable property otherwise.
  // Marks fields that are initialized with a simple double constant.
  void set_is_double_initialized_unsafe(bool value) const {
    ASSERT(IsOriginal());
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(DoubleInitializedBit::update(value, untag()->kind_bits_));
  }

  void set_is_double_initialized(bool value) const {
    DEBUG_ASSERT(
        IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
    set_is_double_initialized_unsafe(value);
  }

  bool initializer_changed_after_initialization() const {
    return InitializerChangedAfterInitializatonBit::decode(kind_bits());
  }
  void set_initializer_changed_after_initialization(bool value) const {
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(InitializerChangedAfterInitializatonBit::update(
        value, untag()->kind_bits_));
  }

  bool has_pragma() const { return HasPragmaBit::decode(kind_bits()); }
  void set_has_pragma(bool value) const {
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(HasPragmaBit::update(value, untag()->kind_bits_));
  }

  bool is_covariant() const { return CovariantBit::decode(kind_bits()); }
  void set_is_covariant(bool value) const {
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(CovariantBit::update(value, untag()->kind_bits_));
  }

  bool is_generic_covariant_impl() const {
    return GenericCovariantImplBit::decode(kind_bits());
  }
  void set_is_generic_covariant_impl(bool value) const {
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(GenericCovariantImplBit::update(value, untag()->kind_bits_));
  }

  intptr_t kernel_offset() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    return 0;
#else
    return untag()->kernel_offset_;
#endif
  }

  void set_kernel_offset(intptr_t value) const {
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
#else
    ASSERT(value >= 0);
    StoreNonPointer(&untag()->kernel_offset_, value);
#endif
  }

  void InheritKernelOffsetFrom(const Field& src) const;

  ExternalTypedDataPtr KernelData() const;

  intptr_t KernelDataProgramOffset() const;

  // Called during class finalization.
  inline void SetOffset(intptr_t host_offset_in_bytes,
                        intptr_t target_offset_in_bytes) const;

  inline intptr_t HostOffset() const;
  static intptr_t host_offset_or_field_id_offset() {
    return OFFSET_OF(UntaggedField, host_offset_or_field_id_);
  }

  inline intptr_t TargetOffset() const;
  static inline intptr_t TargetOffsetOf(FieldPtr field);

  ObjectPtr StaticConstFieldValue() const;
  void SetStaticConstFieldValue(const Instance& value,
                                bool assert_initializing_store = true) const;

  inline ObjectPtr StaticValue() const;
  void SetStaticValue(const Object& value) const;

  inline intptr_t field_id() const;
  inline void set_field_id(intptr_t field_id) const;
  inline void set_field_id_unsafe(intptr_t field_id) const;

  ClassPtr Owner() const;
  ClassPtr Origin() const;  // Either mixin class, or same as owner().
  ScriptPtr Script() const;
  ObjectPtr RawOwner() const;

  AbstractTypePtr type() const { return untag()->type(); }
  // Used by class finalizer, otherwise initialized in constructor.
  void SetFieldType(const AbstractType& value) const;
  void SetFieldTypeSafe(const AbstractType& value) const;

  DART_WARN_UNUSED_RESULT
  ErrorPtr VerifyEntryPoint(EntryPointPragma kind) const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedField));
  }

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

  static FieldPtr NewTopLevel(const String& name,
                              bool is_final,
                              bool is_const,
                              bool is_late,
                              const Object& owner,
                              TokenPosition token_pos,
                              TokenPosition end_token_pos);

  // Allocate new field object, clone values from this field. The
  // original is specified.
  FieldPtr Clone(const Field& original) const;

  static intptr_t kind_bits_offset() {
    return OFFSET_OF(UntaggedField, kind_bits_);
  }

  TokenPosition token_pos() const { return untag()->token_pos_; }
  TokenPosition end_token_pos() const { return untag()->end_token_pos_; }

  int32_t SourceFingerprint() const;

  StringPtr InitializingExpression() const;

  bool has_nontrivial_initializer() const {
    return HasNontrivialInitializerBit::decode(kind_bits());
  }
  // Called by parser after allocating field.
  void set_has_nontrivial_initializer_unsafe(
      bool has_nontrivial_initializer) const {
    ASSERT(IsOriginal());
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(HasNontrivialInitializerBit::update(
        has_nontrivial_initializer, untag()->kind_bits_));
  }
  void set_has_nontrivial_initializer(bool has_nontrivial_initializer) const {
    DEBUG_ASSERT(
        IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
    set_has_nontrivial_initializer_unsafe(has_nontrivial_initializer);
  }

  bool has_initializer() const {
    return HasInitializerBit::decode(kind_bits());
  }
  // Called by parser after allocating field.
  void set_has_initializer_unsafe(bool has_initializer) const {
    ASSERT(IsOriginal());
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(
        HasInitializerBit::update(has_initializer, untag()->kind_bits_));
  }
  void set_has_initializer(bool has_initializer) const {
    DEBUG_ASSERT(
        IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
    set_has_initializer_unsafe(has_initializer);
  }

  bool has_trivial_initializer() const {
    return has_initializer() && !has_nontrivial_initializer();
  }

  bool is_non_nullable_integer() const {
    return IsNonNullableIntBit::decode(kind_bits());
  }

  void set_is_non_nullable_integer(bool is_non_nullable_integer) const {
    ASSERT(Thread::Current()->IsMutatorThread());
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(IsNonNullableIntBit::update(is_non_nullable_integer,
                                              untag()->kind_bits_));
  }

  StaticTypeExactnessState static_type_exactness_state() const {
    return StaticTypeExactnessState::Decode(
        LoadNonPointer<int8_t, std::memory_order_relaxed>(
            &untag()->static_type_exactness_state_));
  }

  void set_static_type_exactness_state(StaticTypeExactnessState state) const {
    DEBUG_ASSERT(
        IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
    set_static_type_exactness_state_unsafe(state);
  }

  void set_static_type_exactness_state_unsafe(
      StaticTypeExactnessState state) const {
    StoreNonPointer<int8_t, int8_t, std::memory_order_relaxed>(
        &untag()->static_type_exactness_state_, state.Encode());
  }

  static intptr_t static_type_exactness_state_offset() {
    return OFFSET_OF(UntaggedField, static_type_exactness_state_);
  }

  // Return class id that any non-null value read from this field is guaranteed
  // to have or kDynamicCid if such class id is not known.
  // Stores to this field must update this information hence the name.
  intptr_t guarded_cid() const;

  void set_guarded_cid(intptr_t cid) const {
    DEBUG_ASSERT(
        IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
    set_guarded_cid_unsafe(cid);
  }
  void set_guarded_cid_unsafe(intptr_t cid) const {
    StoreNonPointer<ClassIdTagType, ClassIdTagType, std::memory_order_relaxed>(
        &untag()->guarded_cid_, cid);
  }
  static intptr_t guarded_cid_offset() {
    return OFFSET_OF(UntaggedField, guarded_cid_);
  }
  // Return the list length that any list stored in this field is guaranteed
  // to have. If length is kUnknownFixedLength the length has not
  // been determined. If length is kNoFixedLength this field has multiple
  // list lengths associated with it and cannot be predicted.
  intptr_t guarded_list_length() const;
  void set_guarded_list_length_unsafe(intptr_t list_length) const;
  void set_guarded_list_length(intptr_t list_length) const {
    DEBUG_ASSERT(
        IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
    set_guarded_list_length_unsafe(list_length);
  }
  static intptr_t guarded_list_length_offset() {
    return OFFSET_OF(UntaggedField, guarded_list_length_);
  }
  intptr_t guarded_list_length_in_object_offset() const;
  void set_guarded_list_length_in_object_offset_unsafe(intptr_t offset) const;
  void set_guarded_list_length_in_object_offset(intptr_t offset) const {
    DEBUG_ASSERT(
        IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
    set_guarded_list_length_in_object_offset_unsafe(offset);
  }
  static intptr_t guarded_list_length_in_object_offset_offset() {
    return OFFSET_OF(UntaggedField, guarded_list_length_in_object_offset_);
  }

  bool needs_length_check() const {
    const bool r = guarded_list_length() >= Field::kUnknownFixedLength;
    ASSERT(!r || is_final());
    return r;
  }

  bool NeedsSetter() const;
  bool NeedsGetter() const;

  bool NeedsInitializationCheckOnLoad() const {
    return needs_load_guard() || (is_late() && !has_trivial_initializer());
  }

  const char* GuardedPropertiesAsCString() const;

  intptr_t UnboxedFieldCid() const { return guarded_cid(); }

  bool is_unboxing_candidate() const {
    return UnboxingCandidateBit::decode(kind_bits());
  }

  // Default 'true', set to false once optimizing compiler determines it should
  // be boxed.
  void set_is_unboxing_candidate_unsafe(bool b) const {
    set_kind_bits(UnboxingCandidateBit::update(b, untag()->kind_bits_));
  }

  void set_is_unboxing_candidate(bool b) const {
    DEBUG_ASSERT(
        IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
    set_is_unboxing_candidate_unsafe(b);
  }

  enum {
    kUnknownLengthOffset = -1,
    kUnknownFixedLength = -1,
    kNoFixedLength = -2,
  };
  void set_is_late(bool value) const {
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(IsLateBit::update(value, untag()->kind_bits_));
  }
  void set_is_extension_member(bool value) const {
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(IsExtensionMemberBit::update(value, untag()->kind_bits_));
  }
  void set_needs_load_guard(bool value) const {
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(NeedsLoadGuardBit::update(value, untag()->kind_bits_));
  }
  // Returns false if any value read from this field is guaranteed to be
  // not null.
  // Internally we is_nullable_ field contains either kNullCid (nullable) or
  // kIllegalCid (non-nullable) instead of boolean. This is done to simplify
  // guarding sequence in the generated code.
  bool is_nullable() const;
  void set_is_nullable(bool val) const {
    DEBUG_ASSERT(
        IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
    set_is_nullable_unsafe(val);
  }
  bool is_nullable_unsafe() const {
    return LoadNonPointer<ClassIdTagType, std::memory_order_relaxed>(
               &untag()->is_nullable_) == kNullCid;
  }
  void set_is_nullable_unsafe(bool val) const {
    StoreNonPointer<ClassIdTagType, ClassIdTagType, std::memory_order_relaxed>(
        &untag()->is_nullable_, val ? kNullCid : kIllegalCid);
  }
  static intptr_t is_nullable_offset() {
    return OFFSET_OF(UntaggedField, is_nullable_);
  }

  // Record store of the given value into this field. May trigger
  // deoptimization of dependent optimized code.
  void RecordStore(const Object& value) const;

  void InitializeGuardedListLengthInObjectOffset(bool unsafe = false) const;

  // Return the list of optimized code objects that were optimized under
  // assumptions about guarded class id and nullability of this field.
  // These code objects must be deoptimized when field's properties change.
  // Code objects are held weakly via an indirection through WeakProperty.
  ArrayPtr dependent_code() const;
  void set_dependent_code(const Array& array) const;

  // Add the given code object to the list of dependent ones.
  void RegisterDependentCode(const Code& code) const;

  // Deoptimize all dependent code objects.
  void DeoptimizeDependentCode(bool are_mutators_stopped = false) const;

  // Used by background compiler to check consistency of field copy with its
  // original.
  bool IsConsistentWith(const Field& field) const;

  bool IsUninitialized() const;

  // Run initializer and set field value.
  DART_WARN_UNUSED_RESULT ErrorPtr
  InitializeInstance(const Instance& instance) const;
  DART_WARN_UNUSED_RESULT ErrorPtr InitializeStatic() const;

  // Run initializer only.
  DART_WARN_UNUSED_RESULT ObjectPtr EvaluateInitializer() const;

  FunctionPtr EnsureInitializerFunction() const;
  FunctionPtr InitializerFunction() const {
    return untag()->initializer_function<std::memory_order_acquire>();
  }
  void SetInitializerFunction(const Function& initializer) const;
  bool HasInitializerFunction() const;
  static intptr_t initializer_function_offset() {
    return OFFSET_OF(UntaggedField, initializer_function_);
  }

  // For static fields only. Constructs a closure that gets/sets the
  // field value.
  InstancePtr GetterClosure() const;
  InstancePtr SetterClosure() const;
  InstancePtr AccessorClosure(bool make_setter) const;

  // Constructs getter and setter names for fields and vice versa.
  static StringPtr GetterName(const String& field_name);
  static StringPtr GetterSymbol(const String& field_name);
  // Returns String::null() if getter symbol does not exist.
  static StringPtr LookupGetterSymbol(const String& field_name);
  static StringPtr SetterName(const String& field_name);
  static StringPtr SetterSymbol(const String& field_name);
  // Returns String::null() if setter symbol does not exist.
  static StringPtr LookupSetterSymbol(const String& field_name);
  static StringPtr NameFromGetter(const String& getter_name);
  static StringPtr NameFromSetter(const String& setter_name);
  static StringPtr NameFromInit(const String& init_name);
  static bool IsGetterName(const String& function_name);
  static bool IsSetterName(const String& function_name);
  static bool IsInitName(const String& function_name);

#if !defined(DART_PRECOMPILED_RUNTIME)
  SubtypeTestCachePtr type_test_cache() const {
    return untag()->type_test_cache();
  }
  void set_type_test_cache(const SubtypeTestCache& cache) const;
#endif

  // Unboxed fields require exclusive ownership of the box.
  // Ensure this by cloning the box if necessary.
  const Object* CloneForUnboxed(const Object& value) const;

 private:
  static void 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);
  friend class StoreInstanceFieldInstr;  // Generated code access to bit field.

  enum {
    kConstBit = 0,
    kStaticBit,
    kFinalBit,
    kHasNontrivialInitializerBit,
    kUnboxingCandidateBit,
    kReflectableBit,
    kDoubleInitializedBit,
    kInitializerChangedAfterInitializatonBit,
    kHasPragmaBit,
    kCovariantBit,
    kGenericCovariantImplBit,
    kIsLateBit,
    kIsExtensionMemberBit,
    kNeedsLoadGuardBit,
    kHasInitializerBit,
    kIsNonNullableIntBit,
  };
  class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
  class StaticBit : public BitField<uint16_t, bool, kStaticBit, 1> {};
  class FinalBit : public BitField<uint16_t, bool, kFinalBit, 1> {};
  class HasNontrivialInitializerBit
      : public BitField<uint16_t, bool, kHasNontrivialInitializerBit, 1> {};
  class UnboxingCandidateBit
      : public BitField<uint16_t, bool, kUnboxingCandidateBit, 1> {};
  class ReflectableBit : public BitField<uint16_t, bool, kReflectableBit, 1> {};
  class DoubleInitializedBit
      : public BitField<uint16_t, bool, kDoubleInitializedBit, 1> {};
  class InitializerChangedAfterInitializatonBit
      : public BitField<uint16_t,
                        bool,
                        kInitializerChangedAfterInitializatonBit,
                        1> {};
  class HasPragmaBit : public BitField<uint16_t, bool, kHasPragmaBit, 1> {};
  class CovariantBit : public BitField<uint16_t, bool, kCovariantBit, 1> {};
  class GenericCovariantImplBit
      : public BitField<uint16_t, bool, kGenericCovariantImplBit, 1> {};
  class IsLateBit : public BitField<uint16_t, bool, kIsLateBit, 1> {};
  class IsExtensionMemberBit
      : public BitField<uint16_t, bool, kIsExtensionMemberBit, 1> {};
  class NeedsLoadGuardBit
      : public BitField<uint16_t, bool, kNeedsLoadGuardBit, 1> {};
  class HasInitializerBit
      : public BitField<uint16_t, bool, kHasInitializerBit, 1> {};
  class IsNonNullableIntBit
      : public BitField<uint16_t, bool, kIsNonNullableIntBit, 1> {};

  // Force this field's guard to be dynamic and deoptimize dependent code.
  void ForceDynamicGuardedCidAndLength() const;

  void set_name(const String& value) const;
  void set_is_static(bool is_static) const {
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(StaticBit::update(is_static, untag()->kind_bits_));
  }
  void set_is_final(bool is_final) const {
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(FinalBit::update(is_final, untag()->kind_bits_));
  }
  void set_is_const(bool value) const {
    // TODO(36097): Once concurrent access is possible ensure updates are safe.
    set_kind_bits(ConstBit::update(value, untag()->kind_bits_));
  }
  void set_owner(const Object& value) const { untag()->set_owner(value.ptr()); }
  void set_token_pos(TokenPosition token_pos) const {
    StoreNonPointer(&untag()->token_pos_, token_pos);
  }
  void set_end_token_pos(TokenPosition token_pos) const {
    StoreNonPointer(&untag()->end_token_pos_, token_pos);
  }
  void set_kind_bits(uint16_t value) const {
    StoreNonPointer<uint16_t, uint16_t, std::memory_order_release>(
        &untag()->kind_bits_, value);
  }

  static FieldPtr New();

  FINAL_HEAP_OBJECT_IMPLEMENTATION(Field, Object);
  friend class Class;
  friend class UntaggedField;
  friend class FieldSerializationCluster;
  friend class FieldDeserializationCluster;
};

class Script : public Object {
 public:
  StringPtr url() const { return untag()->url(); }
  void set_url(const String& value) const;

  // The actual url which was loaded from disk, if provided by the embedder.
  StringPtr resolved_url() const;
  bool HasSource() const;
  StringPtr Source() const;
  bool IsPartOfDartColonLibrary() const;

  void LookupSourceAndLineStarts(Zone* zone) const;
  GrowableObjectArrayPtr GenerateLineNumberArray() const;

  intptr_t line_offset() const { return 0; }
  intptr_t col_offset() const { return 0; }
  // Returns the max real token position for this script, or kNoSource
  // if there is no line starts information.
  TokenPosition MaxPosition() const;

  // The load time in milliseconds since epoch.
  int64_t load_timestamp() const { return untag()->load_timestamp_; }

  KernelProgramInfoPtr kernel_program_info() const {
    return untag()->kernel_program_info();
  }
  void set_kernel_program_info(const KernelProgramInfo& info) const;

  intptr_t kernel_script_index() const { return untag()->kernel_script_index_; }
  void set_kernel_script_index(const intptr_t kernel_script_index) const;

  TypedDataPtr kernel_string_offsets() const;

  TypedDataPtr line_starts() const;

#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
  ExternalTypedDataPtr constant_coverage() const;

  void set_constant_coverage(const ExternalTypedData& value) const;
#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

  void set_line_starts(const TypedData& value) const;

  void set_debug_positions(const Array& value) const;

  LibraryPtr FindLibrary() const;
  StringPtr GetLine(intptr_t line_number, Heap::Space space = Heap::kNew) const;
  StringPtr GetSnippet(intptr_t from_line,
                       intptr_t from_column,
                       intptr_t to_line,
                       intptr_t to_column) const;

  // For real token positions when line starts are available, returns whether or
  // not a GetTokenLocation call would succeed. Returns true for non-real token
  // positions or if there is no line starts information.
  bool IsValidTokenPosition(TokenPosition token_pos) const;

  // Returns whether a line and column could be computed for the given token
  // position and, if so, sets *line and *column (if not nullptr).
  bool GetTokenLocation(const TokenPosition& token_pos,
                        intptr_t* line,
                        intptr_t* column = nullptr) const;

  // Returns the length of the token at the given position. If the length cannot
  // be determined, returns a negative value.
  intptr_t GetTokenLength(const TokenPosition& token_pos) const;

  // Returns whether any tokens were found for the given line. When found,
  // *first_token_index and *last_token_index are set to the first and
  // last token on the line, respectively.
  bool TokenRangeAtLine(intptr_t line_number,
                        TokenPosition* first_token_index,
                        TokenPosition* last_token_index) const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedScript));
  }

  static ScriptPtr New(const String& url, const String& source);

  static ScriptPtr New(const String& url,
                       const String& resolved_url,
                       const String& source);

#if !defined(DART_PRECOMPILED_RUNTIME)
  void LoadSourceFromKernel(const uint8_t* kernel_buffer,
                            intptr_t kernel_buffer_len) const;
  bool IsLazyLookupSourceAndLineStarts() const;
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

 private:
#if !defined(DART_PRECOMPILED_RUNTIME)
  bool HasCachedMaxPosition() const;

  void SetLazyLookupSourceAndLineStarts(bool value) const;
  void SetHasCachedMaxPosition(bool value) const;
  void SetCachedMaxPosition(intptr_t value) const;
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

  void set_resolved_url(const String& value) const;
  void set_source(const String& value) const;
  void set_load_timestamp(int64_t value) const;
  ArrayPtr debug_positions() const;

  static ScriptPtr New();

  FINAL_HEAP_OBJECT_IMPLEMENTATION(Script, Object);
  friend class Class;
  friend class Precompiler;
};

class DictionaryIterator : public ValueObject {
 public:
  explicit DictionaryIterator(const Library& library);

  bool HasNext() const { return next_ix_ < size_; }

  // Returns next non-null raw object.
  ObjectPtr GetNext();

 private:
  void MoveToNextObject();

  const Array& array_;
  const int size_;  // Number of elements to iterate over.
  int next_ix_;     // Index of next element.

  friend class ClassDictionaryIterator;
  DISALLOW_COPY_AND_ASSIGN(DictionaryIterator);
};

class ClassDictionaryIterator : public DictionaryIterator {
 public:
  enum IterationKind {
    // TODO(hausner): fix call sites that use kIteratePrivate. There is only
    // one top-level class per library left, not an array to iterate over.
    kIteratePrivate,
    kNoIteratePrivate
  };

  ClassDictionaryIterator(const Library& library,
                          IterationKind kind = kNoIteratePrivate);

  bool HasNext() const {
    return (next_ix_ < size_) || !toplevel_class_.IsNull();
  }

  // Returns a non-null raw class.
  ClassPtr GetNextClass();

 private:
  void MoveToNextClass();

  Class& toplevel_class_;

  DISALLOW_COPY_AND_ASSIGN(ClassDictionaryIterator);
};

class Library : public Object {
 public:
  StringPtr name() const { return untag()->name(); }
  void SetName(const String& name) const;

  StringPtr url() const { return untag()->url(); }
  static StringPtr UrlOf(LibraryPtr lib) { return lib->untag()->url(); }
  StringPtr private_key() const { return untag()->private_key(); }
  bool LoadNotStarted() const {
    return untag()->load_state_ == UntaggedLibrary::kAllocated;
  }
  bool LoadRequested() const {
    return untag()->load_state_ == UntaggedLibrary::kLoadRequested;
  }
  bool LoadInProgress() const {
    return untag()->load_state_ == UntaggedLibrary::kLoadInProgress;
  }
  void SetLoadRequested() const;
  void SetLoadInProgress() const;
  bool Loaded() const {
    return untag()->load_state_ == UntaggedLibrary::kLoaded;
  }
  void SetLoaded() const;

  LoadingUnitPtr loading_unit() const { return untag()->loading_unit(); }
  void set_loading_unit(const LoadingUnit& value) const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedLibrary));
  }

  static LibraryPtr New(const String& url);

  ObjectPtr Invoke(const String& selector,
                   const Array& arguments,
                   const Array& argument_names,
                   bool respect_reflectable = true,
                   bool check_is_entrypoint = false) const;
  ObjectPtr InvokeGetter(const String& selector,
                         bool throw_nsm_if_absent,
                         bool respect_reflectable = true,
                         bool check_is_entrypoint = false) const;
  ObjectPtr InvokeSetter(const String& selector,
                         const Instance& argument,
                         bool respect_reflectable = true,
                         bool check_is_entrypoint = false) const;

  // Evaluate the given expression as if it appeared in an top-level method of
  // this library and return the resulting value, or an error object if
  // evaluating the expression fails. The method has the formal (type)
  // parameters given in (type_)param_names, and is invoked with the (type)
  // argument values given in (type_)param_values.
  ObjectPtr EvaluateCompiledExpression(
      const ExternalTypedData& kernel_buffer,
      const Array& type_definitions,
      const Array& param_values,
      const TypeArguments& type_param_values) const;

  // Library scope name dictionary.
  //
  // TODO(turnidge): The Lookup functions are not consistent in how
  // they deal with private names.  Go through and make them a bit
  // more regular.
  void AddClass(const Class& cls) const;
  void AddObject(const Object& obj, const String& name) const;
  ObjectPtr LookupReExport(const String& name,
                           ZoneGrowableArray<intptr_t>* visited = NULL) const;
  ObjectPtr LookupObjectAllowPrivate(const String& name) const;
  ObjectPtr LookupLocalOrReExportObject(const String& name) const;
  ObjectPtr LookupImportedObject(const String& name) const;
  ClassPtr LookupClass(const String& name) const;
  ClassPtr LookupClassAllowPrivate(const String& name) const;
  ClassPtr SlowLookupClassAllowMultiPartPrivate(const String& name) const;
  ClassPtr LookupLocalClass(const String& name) const;
  FieldPtr LookupFieldAllowPrivate(const String& name) const;
  FieldPtr LookupLocalField(const String& name) const;
  FunctionPtr LookupFunctionAllowPrivate(const String& name) const;
  FunctionPtr LookupLocalFunction(const String& name) const;
  LibraryPrefixPtr LookupLocalLibraryPrefix(const String& name) const;

  // Look up a Script based on a url. If 'useResolvedUri' is not provided or is
  // false, 'url' should have a 'dart:' scheme for Dart core libraries,
  // a 'package:' scheme for packages, and 'file:' scheme otherwise.
  //
  // If 'useResolvedUri' is true, 'url' should have a 'org-dartlang-sdk:' scheme
  // for Dart core libraries and a 'file:' scheme otherwise.
  ScriptPtr LookupScript(const String& url, bool useResolvedUri = false) const;
  ArrayPtr LoadedScripts() const;

  // Resolve name in the scope of this library. First check the cache
  // of already resolved names for this library. Then look in the
  // local dictionary for the unmangled name N, the getter name get:N
  // and setter name set:N.
  // If the local dictionary contains no entry for these names,
  // look in the scopes of all libraries that are imported
  // without a library prefix.
  ObjectPtr ResolveName(const String& name) const;

  void AddAnonymousClass(const Class& cls) const;

  void AddExport(const Namespace& ns) const;

  void AddMetadata(const Object& declaration, intptr_t kernel_offset) const;
  ObjectPtr GetMetadata(const Object& declaration) const;

  // Tries to finds a @pragma annotation on [object].
  //
  // If successful returns `true`. If an error happens during constant
  // evaluation, returns `false.
  //
  // If [only_core] is true, then the annotations on the object will only
  // be inspected if it is part of a core library.
  //
  // If [multiple] is true, then sets [options] to an GrowableObjectArray
  // containing all results and [options] may not be nullptr.
  //
  // WARNING: If the isolate received an [UnwindError] this function will not
  // return and rather unwinds until the enclosing setjmp() handler.
  static bool FindPragma(Thread* T,
                         bool only_core,
                         const Object& object,
                         const String& pragma_name,
                         bool multiple = false,
                         Object* options = nullptr);

  ClassPtr toplevel_class() const { return untag()->toplevel_class(); }
  void set_toplevel_class(const Class& value) const;

  GrowableObjectArrayPtr used_scripts() const {
    return untag()->used_scripts();
  }

  // Library imports.
  ArrayPtr imports() const { return untag()->imports(); }
  ArrayPtr exports() const { return untag()->exports(); }
  void AddImport(const Namespace& ns) const;
  intptr_t num_imports() const { return untag()->num_imports_; }
  NamespacePtr ImportAt(intptr_t index) const;
  LibraryPtr ImportLibraryAt(intptr_t index) const;

  ArrayPtr dependencies() const { return untag()->dependencies(); }
  void set_dependencies(const Array& deps) const;

  void DropDependenciesAndCaches() const;

  // Resolving native methods for script loaded in the library.
  Dart_NativeEntryResolver native_entry_resolver() const {
    return LoadNonPointer<Dart_NativeEntryResolver, std::memory_order_relaxed>(
        &untag()->native_entry_resolver_);
  }
  void set_native_entry_resolver(Dart_NativeEntryResolver value) const {
    StoreNonPointer<Dart_NativeEntryResolver, Dart_NativeEntryResolver,
                    std::memory_order_relaxed>(&untag()->native_entry_resolver_,
                                               value);
  }
  Dart_NativeEntrySymbol native_entry_symbol_resolver() const {
    return LoadNonPointer<Dart_NativeEntrySymbol, std::memory_order_relaxed>(
        &untag()->native_entry_symbol_resolver_);
  }
  void set_native_entry_symbol_resolver(
      Dart_NativeEntrySymbol native_symbol_resolver) const {
    StoreNonPointer<Dart_NativeEntrySymbol, Dart_NativeEntrySymbol,
                    std::memory_order_relaxed>(
        &untag()->native_entry_symbol_resolver_, native_symbol_resolver);
  }

  // Resolver for FFI native function pointers.
  Dart_FfiNativeResolver ffi_native_resolver() const {
    return LoadNonPointer<Dart_FfiNativeResolver, std::memory_order_relaxed>(
        &untag()->ffi_native_resolver_);
  }
  void set_ffi_native_resolver(Dart_FfiNativeResolver value) const {
    StoreNonPointer<Dart_FfiNativeResolver, Dart_FfiNativeResolver,
                    std::memory_order_relaxed>(&untag()->ffi_native_resolver_,
                                               value);
  }

  bool is_in_fullsnapshot() const {
    return UntaggedLibrary::InFullSnapshotBit::decode(untag()->flags_);
  }
  void set_is_in_fullsnapshot(bool value) const {
    set_flags(
        UntaggedLibrary::InFullSnapshotBit::update(value, untag()->flags_));
  }

  bool is_nnbd() const {
    return UntaggedLibrary::NnbdBit::decode(untag()->flags_);
  }
  void set_is_nnbd(bool value) const {
    set_flags(UntaggedLibrary::NnbdBit::update(value, untag()->flags_));
  }

  NNBDMode nnbd_mode() const {
    return is_nnbd() ? NNBDMode::kOptedInLib : NNBDMode::kLegacyLib;
  }

  NNBDCompiledMode nnbd_compiled_mode() const {
    return static_cast<NNBDCompiledMode>(
        UntaggedLibrary::NnbdCompiledModeBits::decode(untag()->flags_));
  }
  void set_nnbd_compiled_mode(NNBDCompiledMode value) const {
    set_flags(UntaggedLibrary::NnbdCompiledModeBits::update(
        static_cast<uint8_t>(value), untag()->flags_));
  }

  StringPtr PrivateName(const String& name) const;

  intptr_t index() const { return untag()->index_; }
  void set_index(intptr_t value) const {
    ASSERT((value == -1) ||
           ((value >= 0) && (value < std::numeric_limits<classid_t>::max())));
    StoreNonPointer(&untag()->index_, value);
  }

  void Register(Thread* thread) const;
  static void RegisterLibraries(Thread* thread,
                                const GrowableObjectArray& libs);

  bool IsDebuggable() const {
    return UntaggedLibrary::DebuggableBit::decode(untag()->flags_);
  }
  void set_debuggable(bool value) const {
    set_flags(UntaggedLibrary::DebuggableBit::update(value, untag()->flags_));
  }

  bool is_dart_scheme() const {
    return UntaggedLibrary::DartSchemeBit::decode(untag()->flags_);
  }
  void set_is_dart_scheme(bool value) const {
    set_flags(UntaggedLibrary::DartSchemeBit::update(value, untag()->flags_));
  }

  // Includes 'dart:async', 'dart:typed_data', etc.
  bool IsAnyCoreLibrary() const;

  inline intptr_t UrlHash() const;

  ExternalTypedDataPtr kernel_data() const { return untag()->kernel_data(); }
  void set_kernel_data(const ExternalTypedData& data) const;

  intptr_t kernel_offset() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    return 0;
#else
    return untag()->kernel_offset_;
#endif
  }

  void set_kernel_offset(intptr_t value) const {
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
#else
    ASSERT(value >= 0);
    StoreNonPointer(&untag()->kernel_offset_, value);
#endif
  }

  static LibraryPtr LookupLibrary(Thread* thread, const String& url);
  static LibraryPtr GetLibrary(intptr_t index);

  static void InitCoreLibrary(IsolateGroup* isolate_group);
  static void InitNativeWrappersLibrary(IsolateGroup* isolate_group,
                                        bool is_kernel_file);

  static LibraryPtr AsyncLibrary();
  static LibraryPtr ConvertLibrary();
  static LibraryPtr CoreLibrary();
  static LibraryPtr CollectionLibrary();
  static LibraryPtr DeveloperLibrary();
  static LibraryPtr FfiLibrary();
  static LibraryPtr InternalLibrary();
  static LibraryPtr IsolateLibrary();
  static LibraryPtr MathLibrary();
#if !defined(DART_PRECOMPILED_RUNTIME)
  static LibraryPtr MirrorsLibrary();
#endif
  static LibraryPtr NativeWrappersLibrary();
  static LibraryPtr TypedDataLibrary();
  static LibraryPtr VMServiceLibrary();

  // Eagerly compile all classes and functions in the library.
  static ErrorPtr CompileAll(bool ignore_error = false);
#if !defined(DART_PRECOMPILED_RUNTIME)
  // Finalize all classes in all libraries.
  static ErrorPtr FinalizeAllClasses();
#endif

#if defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME)
  // Checks function fingerprints. Prints mismatches and aborts if
  // mismatch found.
  static void CheckFunctionFingerprints();
#endif  // defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME).

  static bool IsPrivate(const String& name);

  // Construct the full name of a corelib member.
  static const String& PrivateCoreLibName(const String& member);

  // Returns true if [name] matches full name of corelib [member].
  static bool IsPrivateCoreLibName(const String& name, const String& member);

  // Lookup class in the core lib which also contains various VM
  // helper methods and classes. Allow look up of private classes.
  static ClassPtr LookupCoreClass(const String& class_name);

  // Return Function::null() if function does not exist in libs.
  static FunctionPtr GetFunction(const GrowableArray<Library*>& libs,
                                 const char* class_name,
                                 const char* function_name);

  // Character used to indicate a private identifier.
  static const char kPrivateIdentifierStart = '_';

  // Character used to separate private identifiers from
  // the library-specific key.
  static const char kPrivateKeySeparator = '@';

  void CheckReload(const Library& replacement,
                   ProgramReloadContext* context) const;

  // Returns a closure of top level function 'name' in the exported namespace
  // of this library. If a top level function 'name' does not exist we look
  // for a top level getter 'name' that returns a closure.
  ObjectPtr GetFunctionClosure(const String& name) const;

  // Ensures that all top-level functions and variables (fields) are loaded.
  void EnsureTopLevelClassIsFinalized() const;

 private:
  static const int kInitialImportsCapacity = 4;
  static const int kImportsCapacityIncrement = 8;

  static LibraryPtr New();

  // These methods are only used by the Precompiler to obfuscate
  // the name and url.
  void set_name(const String& name) const;
  void set_url(const String& url) const;

  void set_num_imports(intptr_t value) const;
  void set_flags(uint8_t flags) const;
  bool HasExports() const;
  ArrayPtr loaded_scripts() const { return untag()->loaded_scripts(); }
  ArrayPtr metadata() const {
    DEBUG_ASSERT(
        IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
    return untag()->metadata();
  }
  void set_metadata(const Array& value) const;
  ArrayPtr dictionary() const { return untag()->dictionary(); }
  void InitClassDictionary() const;

  ArrayPtr resolved_names() const { return untag()->resolved_names(); }
  bool LookupResolvedNamesCache(const String& name, Object* obj) const;
  void AddToResolvedNamesCache(const String& name, const Object& obj) const;
  void InitResolvedNamesCache() const;
  void ClearResolvedNamesCache() const;
  void InvalidateResolvedName(const String& name) const;
  void InvalidateResolvedNamesCache() const;

  ArrayPtr exported_names() const { return untag()->exported_names(); }
  bool LookupExportedNamesCache(const String& name, Object* obj) const;
  void AddToExportedNamesCache(const String& name, const Object& obj) const;
  void InitExportedNamesCache() const;
  void ClearExportedNamesCache() const;
  static void InvalidateExportedNamesCaches();

  void InitImportList() const;
  void RehashDictionary(const Array& old_dict, intptr_t new_dict_size) const;
  static LibraryPtr NewLibraryHelper(const String& url, bool import_core_lib);
  ObjectPtr LookupEntry(const String& name, intptr_t* index) const;
  ObjectPtr LookupLocalObjectAllowPrivate(const String& name) const;
  ObjectPtr LookupLocalObject(const String& name) const;

  void AllocatePrivateKey() const;

  FINAL_HEAP_OBJECT_IMPLEMENTATION(Library, Object);

  friend class Bootstrap;
  friend class Class;
  friend class Debugger;
  friend class DictionaryIterator;
  friend class Isolate;
  friend class LibraryDeserializationCluster;
  friend class Namespace;
  friend class Object;
  friend class Precompiler;
};

// A Namespace contains the names in a library dictionary, filtered by
// the show/hide combinators.
class Namespace : public Object {
 public:
  LibraryPtr target() const { return untag()->target(); }
  ArrayPtr show_names() const { return untag()->show_names(); }
  ArrayPtr hide_names() const { return untag()->hide_names(); }
  LibraryPtr owner() const { return untag()->owner(); }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedNamespace));
  }

  bool HidesName(const String& name) const;
  ObjectPtr Lookup(const String& name,
                   ZoneGrowableArray<intptr_t>* trail = nullptr) const;

  static NamespacePtr New(const Library& library,
                          const Array& show_names,
                          const Array& hide_names,
                          const Library& owner);

 private:
  static NamespacePtr New();

  FINAL_HEAP_OBJECT_IMPLEMENTATION(Namespace, Object);
  friend class Class;
  friend class Precompiler;
};

class KernelProgramInfo : public Object {
 public:
  static KernelProgramInfoPtr New(const TypedData& string_offsets,
                                  const ExternalTypedData& string_data,
                                  const TypedData& canonical_names,
                                  const ExternalTypedData& metadata_payload,
                                  const ExternalTypedData& metadata_mappings,
                                  const ExternalTypedData& constants_table,
                                  const Array& scripts,
                                  const Array& libraries_cache,
                                  const Array& classes_cache,
                                  const Object& retained_kernel_blob,
                                  const uint32_t binary_version);

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedKernelProgramInfo));
  }

  TypedDataPtr string_offsets() const { return untag()->string_offsets(); }

  ExternalTypedDataPtr string_data() const { return untag()->string_data(); }

  TypedDataPtr canonical_names() const { return untag()->canonical_names(); }

  ExternalTypedDataPtr metadata_payloads() const {
    return untag()->metadata_payloads();
  }

  ExternalTypedDataPtr metadata_mappings() const {
    return untag()->metadata_mappings();
  }

  ExternalTypedDataPtr constants_table() const {
    return untag()->constants_table();
  }

  void set_constants_table(const ExternalTypedData& value) const;

  ArrayPtr scripts() const { return untag()->scripts(); }
  void set_scripts(const Array& scripts) const;

  ArrayPtr constants() const { return untag()->constants(); }
  void set_constants(const Array& constants) const;

  uint32_t kernel_binary_version() const {
    return untag()->kernel_binary_version_;
  }
  void set_kernel_binary_version(uint32_t version) const;

  // If we load a kernel blob with evaluated constants, then we delay setting
  // the native names of [Function] objects until we've read the constant table
  // (since native names are encoded as constants).
  //
  // This array will hold the functions which might need their native name set.
  GrowableObjectArrayPtr potential_natives() const {
    return untag()->potential_natives();
  }
  void set_potential_natives(const GrowableObjectArray& candidates) const;

  GrowableObjectArrayPtr potential_pragma_functions() const {
    return untag()->potential_pragma_functions();
  }
  void set_potential_pragma_functions(
      const GrowableObjectArray& candidates) const;

  ScriptPtr ScriptAt(intptr_t index) const;

  ArrayPtr libraries_cache() const { return untag()->libraries_cache(); }
  void set_libraries_cache(const Array& cache) const;
  LibraryPtr LookupLibrary(Thread* thread, const Smi& name_index) const;
  LibraryPtr InsertLibrary(Thread* thread,
                           const Smi& name_index,
                           const Library& lib) const;

  ArrayPtr classes_cache() const { return untag()->classes_cache(); }
  void set_classes_cache(const Array& cache) const;
  ClassPtr LookupClass(Thread* thread, const Smi& name_index) const;
  ClassPtr InsertClass(Thread* thread,
                       const Smi& name_index,
                       const Class& klass) const;

 private:
  static KernelProgramInfoPtr New();

  FINAL_HEAP_OBJECT_IMPLEMENTATION(KernelProgramInfo, Object);
  friend class Class;
};

// ObjectPool contains constants, immediates and addresses referenced by
// generated code and deoptimization infos. Each entry has an type associated
// with it which is stored in-inline after all the entries.
class ObjectPool : public Object {
 public:
  using EntryType = compiler::ObjectPoolBuilderEntry::EntryType;
  using Patchability = compiler::ObjectPoolBuilderEntry::Patchability;
  using TypeBits = compiler::ObjectPoolBuilderEntry::TypeBits;
  using PatchableBit = compiler::ObjectPoolBuilderEntry::PatchableBit;

  struct Entry {
    Entry() : raw_value_(), type_() {}
    explicit Entry(const Object* obj)
        : obj_(obj), type_(EntryType::kTaggedObject) {}
    Entry(uword value, EntryType info) : raw_value_(value), type_(info) {}
    union {
      const Object* obj_;
      uword raw_value_;
    };
    EntryType type_;
  };

  intptr_t Length() const { return untag()->length_; }
  void SetLength(intptr_t value) const {
    StoreNonPointer(&untag()->length_, value);
  }

  static intptr_t length_offset() {
    return OFFSET_OF(UntaggedObjectPool, length_);
  }
  static intptr_t data_offset() {
    return OFFSET_OF_RETURNED_VALUE(UntaggedObjectPool, data);
  }
  static intptr_t element_offset(intptr_t index) {
    return OFFSET_OF_RETURNED_VALUE(UntaggedObjectPool, data) +
           sizeof(UntaggedObjectPool::Entry) * index;
  }

  struct ArrayTraits {
    static intptr_t elements_start_offset() {
      return ObjectPool::data_offset();
    }

    static constexpr intptr_t kElementSize = sizeof(UntaggedObjectPool::Entry);
  };

  EntryType TypeAt(intptr_t index) const {
    ASSERT((index >= 0) && (index <= Length()));
    return TypeBits::decode(untag()->entry_bits()[index]);
  }

  Patchability PatchableAt(intptr_t index) const {
    ASSERT((index >= 0) && (index <= Length()));
    return PatchableBit::decode(untag()->entry_bits()[index]);
  }

  static uint8_t EncodeBits(EntryType type, Patchability patchable) {
    return PatchableBit::encode(patchable) | TypeBits::encode(type);
  }

  void SetTypeAt(intptr_t index, EntryType type, Patchability patchable) const {
    ASSERT(index >= 0 && index <= Length());
    const uint8_t bits = EncodeBits(type, patchable);
    StoreNonPointer(&untag()->entry_bits()[index], bits);
  }

  template <std::memory_order order = std::memory_order_relaxed>
  ObjectPtr ObjectAt(intptr_t index) const {
    ASSERT(TypeAt(index) == EntryType::kTaggedObject);
    return LoadPointer<ObjectPtr, order>(&(EntryAddr(index)->raw_obj_));
  }

  template <std::memory_order order = std::memory_order_relaxed>
  void SetObjectAt(intptr_t index, const Object& obj) const {
    ASSERT((TypeAt(index) == EntryType::kTaggedObject) ||
           (TypeAt(index) == EntryType::kImmediate && obj.IsSmi()));
    StorePointer<ObjectPtr, order>(&EntryAddr(index)->raw_obj_, obj.ptr());
  }

  uword RawValueAt(intptr_t index) const {
    ASSERT(TypeAt(index) != EntryType::kTaggedObject);
    return EntryAddr(index)->raw_value_;
  }
  void SetRawValueAt(intptr_t index, uword raw_value) const {
    ASSERT(TypeAt(index) != EntryType::kTaggedObject);
    StoreNonPointer(&EntryAddr(index)->raw_value_, raw_value);
  }

  static intptr_t InstanceSize() {
    ASSERT(sizeof(UntaggedObjectPool) ==
           OFFSET_OF_RETURNED_VALUE(UntaggedObjectPool, data));
    return 0;
  }

  static const intptr_t kBytesPerElement =
      sizeof(UntaggedObjectPool::Entry) + sizeof(uint8_t);
  static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;

  static intptr_t InstanceSize(intptr_t len) {
    // Ensure that variable length data is not adding to the object length.
    ASSERT(sizeof(UntaggedObjectPool) ==
           (sizeof(UntaggedObject) + (1 * kWordSize)));
    ASSERT(0 <= len && len <= kMaxElements);
    return RoundedAllocationSize(sizeof(UntaggedObjectPool) +
                                 (len * kBytesPerElement));
  }

  static ObjectPoolPtr NewFromBuilder(
      const compiler::ObjectPoolBuilder& builder);
  static ObjectPoolPtr New(intptr_t len);

  void CopyInto(compiler::ObjectPoolBuilder* builder) const;

  // Returns the pool index from the offset relative to a tagged ObjectPoolPtr,
  // adjusting for the tag-bit.
  static intptr_t IndexFromOffset(intptr_t offset) {
    ASSERT(
        Utils::IsAligned(offset + kHeapObjectTag, compiler::target::kWordSize));
#if defined(DART_PRECOMPILER)
    return (offset + kHeapObjectTag -
            compiler::target::ObjectPool::element_offset(0)) /
           compiler::target::kWordSize;
#else
    return (offset + kHeapObjectTag - element_offset(0)) / kWordSize;
#endif
  }

  static intptr_t OffsetFromIndex(intptr_t index) {
    return element_offset(index) - kHeapObjectTag;
  }

  void DebugPrint() const;

 private:
  UntaggedObjectPool::Entry const* EntryAddr(intptr_t index) const {
    ASSERT((index >= 0) && (index < Length()));
    return &untag()->data()[index];
  }

  FINAL_HEAP_OBJECT_IMPLEMENTATION(ObjectPool, Object);
  friend class Class;
  friend class Object;
  friend class UntaggedObjectPool;
};

class Instructions : public Object {
 public:
  enum {
    kSizePos = 0,
    kSizeSize = 31,
    kFlagsPos = kSizePos + kSizeSize,
    kFlagsSize = 1,  // Currently, only flag is single entry flag.
  };

  class SizeBits : public BitField<uint32_t, uint32_t, kSizePos, kSizeSize> {};
  class FlagsBits : public BitField<uint32_t, bool, kFlagsPos, kFlagsSize> {};

  // Excludes HeaderSize().
  intptr_t Size() const { return SizeBits::decode(untag()->size_and_flags_); }
  static intptr_t Size(const InstructionsPtr instr) {
    return SizeBits::decode(instr->untag()->size_and_flags_);
  }

  bool HasMonomorphicEntry() const {
    return FlagsBits::decode(untag()->size_and_flags_);
  }
  static bool HasMonomorphicEntry(const InstructionsPtr instr) {
    return FlagsBits::decode(instr->untag()->size_and_flags_);
  }

  uword PayloadStart() const { return PayloadStart(ptr()); }
  uword MonomorphicEntryPoint() const { return MonomorphicEntryPoint(ptr()); }
  uword EntryPoint() const { return EntryPoint(ptr()); }
  static uword PayloadStart(const InstructionsPtr instr) {
    return reinterpret_cast<uword>(instr->untag()) + HeaderSize();
  }

// Note: We keep the checked entrypoint offsets even (emitting NOPs if
// necessary) to allow them to be seen as Smis by the GC.
#if defined(TARGET_ARCH_IA32)
  static const intptr_t kMonomorphicEntryOffsetJIT = 6;
  static const intptr_t kPolymorphicEntryOffsetJIT = 34;
  static const intptr_t kMonomorphicEntryOffsetAOT = 0;
  static const intptr_t kPolymorphicEntryOffsetAOT = 0;
#elif defined(TARGET_ARCH_X64)
  static const intptr_t kMonomorphicEntryOffsetJIT = 8;
  static const intptr_t kPolymorphicEntryOffsetJIT = 40;
  static const intptr_t kMonomorphicEntryOffsetAOT = 8;
  static const intptr_t kPolymorphicEntryOffsetAOT = 22;
#elif defined(TARGET_ARCH_ARM)
  static const intptr_t kMonomorphicEntryOffsetJIT = 0;
  static const intptr_t kPolymorphicEntryOffsetJIT = 40;
  static const intptr_t kMonomorphicEntryOffsetAOT = 0;
  static const intptr_t kPolymorphicEntryOffsetAOT = 12;
#elif defined(TARGET_ARCH_ARM64)
  static const intptr_t kMonomorphicEntryOffsetJIT = 8;
  static const intptr_t kPolymorphicEntryOffsetJIT = 48;
  static const intptr_t kMonomorphicEntryOffsetAOT = 8;
  static const intptr_t kPolymorphicEntryOffsetAOT = 20;
#elif defined(TARGET_ARCH_RISCV32)
  static const intptr_t kMonomorphicEntryOffsetJIT = 6;
  static const intptr_t kPolymorphicEntryOffsetJIT = 42;
  static const intptr_t kMonomorphicEntryOffsetAOT = 6;
  static const intptr_t kPolymorphicEntryOffsetAOT = 16;
#elif defined(TARGET_ARCH_RISCV64)
  static const intptr_t kMonomorphicEntryOffsetJIT = 6;
  static const intptr_t kPolymorphicEntryOffsetJIT = 42;
  static const intptr_t kMonomorphicEntryOffsetAOT = 6;
  static const intptr_t kPolymorphicEntryOffsetAOT = 16;
#else
#error Missing entry offsets for current architecture
#endif

  static uword MonomorphicEntryPoint(const InstructionsPtr instr) {
    uword entry = PayloadStart(instr);
    if (HasMonomorphicEntry(instr)) {
      entry += !FLAG_precompiled_mode ? kMonomorphicEntryOffsetJIT
                                      : kMonomorphicEntryOffsetAOT;
    }
    return entry;
  }

  static uword EntryPoint(const InstructionsPtr instr) {
    uword entry = PayloadStart(instr);
    if (HasMonomorphicEntry(instr)) {
      entry += !FLAG_precompiled_mode ? kPolymorphicEntryOffsetJIT
                                      : kPolymorphicEntryOffsetAOT;
    }
    return entry;
  }

  static const intptr_t kMaxElements =
      (kMaxInt32 - (sizeof(UntaggedInstructions) + sizeof(UntaggedObject) +
                    (2 * kMaxObjectAlignment)));

  // Currently, we align bare instruction payloads on 4 byte boundaries.
  //
  // If we later decide to align on larger boundaries to put entries at the
  // start of cache lines, make sure to account for entry points that are
  // _not_ at the start of the payload.
  static const intptr_t kBarePayloadAlignment = 4;

  // When instructions reside in the heap we align the payloads on word
  // boundaries.
  static const intptr_t kNonBarePayloadAlignment = kWordSize;

  // In the precompiled runtime when running in bare instructions mode,
  // Instructions objects don't exist, just their bare payloads, so we
  // mark them as unreachable in that case.

  static intptr_t HeaderSize() {
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
#endif
    return Utils::RoundUp(sizeof(UntaggedInstructions),
                          kNonBarePayloadAlignment);
  }

  static intptr_t InstanceSize() {
    ASSERT_EQUAL(sizeof(UntaggedInstructions),
                 OFFSET_OF_RETURNED_VALUE(UntaggedInstructions, data));
    return 0;
  }

  static intptr_t InstanceSize(intptr_t size) {
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
#endif
    return RoundedAllocationSize(HeaderSize() + size);
  }

  static InstructionsPtr FromPayloadStart(uword payload_start) {
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
#endif
    return static_cast<InstructionsPtr>(payload_start - HeaderSize() +
                                        kHeapObjectTag);
  }

  bool Equals(const Instructions& other) const {
    return Equals(ptr(), other.ptr());
  }

  static bool Equals(InstructionsPtr a, InstructionsPtr b) {
    // This method should only be called on non-null Instructions objects.
    ASSERT_EQUAL(a->GetClassId(), kInstructionsCid);
    ASSERT_EQUAL(b->GetClassId(), kInstructionsCid);
    // Don't include the object header tags wholesale in the comparison,
    // because the GC tags may differ in JIT mode. In fact, we can skip checking
    // the object header entirely, as we're guaranteed that the cids match,
    // because there are no subclasses for the Instructions class, and the sizes
    // should match if the content size encoded in size_and_flags_ matches.
    if (a->untag()->size_and_flags_ != b->untag()->size_and_flags_) {
      return false;
    }
    NoSafepointScope no_safepoint;
    return memcmp(a->untag()->data(), b->untag()->data(), Size(a)) == 0;
  }

  uint32_t Hash() const { return Hash(ptr()); }

  static uint32_t Hash(const InstructionsPtr instr) {
    return HashBytes(reinterpret_cast<const uint8_t*>(PayloadStart(instr)),
                     Size(instr));
  }

  CodeStatistics* stats() const;
  void set_stats(CodeStatistics* stats) const;

 private:
  friend struct RelocatorTestHelper;

  void SetSize(intptr_t value) const {
    ASSERT(value >= 0);
    StoreNonPointer(&untag()->size_and_flags_,
                    SizeBits::update(value, untag()->size_and_flags_));
  }

  void SetHasMonomorphicEntry(bool value) const {
    StoreNonPointer(&untag()->size_and_flags_,
                    FlagsBits::update(value, untag()->size_and_flags_));
  }

  // New is a private method as RawInstruction and RawCode objects should
  // only be created using the Code::FinalizeCode method. This method creates
  // the RawInstruction and RawCode objects, sets up the pointer offsets
  // and links the two in a GC safe manner.
  static InstructionsPtr New(intptr_t size, bool has_monomorphic_entry);

  FINAL_HEAP_OBJECT_IMPLEMENTATION(Instructions, Object);
  friend class Class;
  friend class Code;
  friend class AssemblyImageWriter;
  friend class BlobImageWriter;
  friend class ImageWriter;
};

// An InstructionsSection contains extra information about serialized AOT
// snapshots.
//
// To avoid changing the embedder to return more information about an AOT
// snapshot and possibly disturbing existing clients of that interface, we
// serialize a single InstructionsSection object at the start of any text
// segments. In bare instructions mode, it also has the benefit of providing
// memory accounting for the instructions payloads and avoiding special casing
// Images with bare instructions payloads in the GC. Otherwise, it is empty
// and the Instructions objects come after it in the Image.
class InstructionsSection : public Object {
 public:
  // Excludes HeaderSize().
  static intptr_t Size(const InstructionsSectionPtr instr) {
    return instr->untag()->payload_length_;
  }
  static intptr_t InstanceSize() {
    ASSERT(sizeof(UntaggedInstructionsSection) ==
           OFFSET_OF_RETURNED_VALUE(UntaggedInstructionsSection, data));
    return 0;
  }

  static intptr_t InstanceSize(intptr_t size) {
    return Utils::RoundUp(HeaderSize() + size, kObjectAlignment);
  }

  static intptr_t HeaderSize() {
    return Utils::RoundUp(sizeof(UntaggedInstructionsSection),
                          Instructions::kBarePayloadAlignment);
  }

  // There are no public instance methods for the InstructionsSection class, as
  // all access to the contents is handled by methods on the Image class.

 private:
  // Note there are no New() methods for InstructionsSection. Instead, the
  // serializer writes the UntaggedInstructionsSection object manually at the
  // start of instructions Images in precompiled snapshots.

  FINAL_HEAP_OBJECT_IMPLEMENTATION(InstructionsSection, Object);
  friend class Class;
};

// Table which maps ranges of machine code to [Code] or
// [CompressedStackMaps] objects.
// Used in AOT in bare instructions mode.
class InstructionsTable : public Object {
 public:
  static intptr_t InstanceSize() { return sizeof(UntaggedInstructionsTable); }

  static InstructionsTablePtr New(intptr_t length,
                                  uword start_pc,
                                  uword end_pc,
                                  uword rodata);

  void SetCodeAt(intptr_t index, CodePtr code) const;

  bool ContainsPc(uword pc) const { return ContainsPc(ptr(), pc); }
  static bool ContainsPc(InstructionsTablePtr table, uword pc);

  static CodePtr FindCode(InstructionsTablePtr table, uword pc);

  static const UntaggedCompressedStackMaps::Payload*
  FindStackMap(InstructionsTablePtr table, uword pc, uword* start_pc);

  static const UntaggedCompressedStackMaps::Payload* GetCanonicalStackMap(
      InstructionsTablePtr table);

  const UntaggedInstructionsTable::Data* rodata() const {
    return ptr()->untag()->rodata_;
  }

  // Returns start address of the instructions entry with given index.
  uword PayloadStartAt(intptr_t index) const {
    return InstructionsTable::PayloadStartAt(this->ptr(), index);
  }
  static uword PayloadStartAt(InstructionsTablePtr table, intptr_t index);

  // Returns entry point of the instructions with given index.
  uword EntryPointAt(intptr_t index) const;

 private:
  uword start_pc() const { return InstructionsTable::start_pc(this->ptr()); }
  static uword start_pc(InstructionsTablePtr table) {
    return table->untag()->start_pc_;
  }

  uword end_pc() const { return InstructionsTable::end_pc(this->ptr()); }
  static uword end_pc(InstructionsTablePtr table) {
    return table->untag()->end_pc_;
  }

  ArrayPtr code_objects() const { return untag()->code_objects_; }

  void set_length(intptr_t value) const;
  void set_start_pc(uword value) const;
  void set_end_pc(uword value) const;
  void set_code_objects(const Array& value) const;
  void set_rodata(uword rodata) const;

  uint32_t ConvertPcToOffset(uword pc) const {
    return InstructionsTable::ConvertPcToOffset(this->ptr(), pc);
  }
  static uint32_t ConvertPcToOffset(InstructionsTablePtr table, uword pc);

  static intptr_t FindEntry(InstructionsTablePtr table,
                            uword pc,
                            intptr_t start_index = 0);

  FINAL_HEAP_OBJECT_IMPLEMENTATION(InstructionsTable, Object);
  friend class Class;
  friend class Deserializer;
};

class LocalVarDescriptors : public Object {
 public:
  intptr_t Length() const;

  StringPtr GetName(intptr_t var_index) const;

  void SetVar(intptr_t var_index,
              const String& name,
              UntaggedLocalVarDescriptors::VarInfo* info) const;

  void GetInfo(intptr_t var_index,
               UntaggedLocalVarDescriptors::VarInfo* info) const;

  static const intptr_t kBytesPerElement =
      sizeof(UntaggedLocalVarDescriptors::VarInfo);
  static const intptr_t kMaxElements = UntaggedLocalVarDescriptors::kMaxIndex;

  static intptr_t InstanceSize() {
    ASSERT(sizeof(UntaggedLocalVarDescriptors) ==
           OFFSET_OF_RETURNED_VALUE(UntaggedLocalVarDescriptors, names));
    return 0;
  }
  static intptr_t InstanceSize(intptr_t len) {
    ASSERT(0 <= len && len <= kMaxElements);
    return RoundedAllocationSize(
        sizeof(UntaggedLocalVarDescriptors) +
        (len * kWordSize)  // RawStrings for names.
        + (len * sizeof(UntaggedLocalVarDescriptors::VarInfo)));
  }

  static LocalVarDescriptorsPtr New(intptr_t num_variables);

  static const char* KindToCString(
      UntaggedLocalVarDescriptors::VarInfoKind kind);

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(LocalVarDescriptors, Object);
  friend class Class;
  friend class Object;
};

class PcDescriptors : public Object {
 public:
  static const intptr_t kBytesPerElement = 1;
  static const intptr_t kMaxElements = kMaxInt32 / kBytesPerElement;

  static intptr_t HeaderSize() { return sizeof(UntaggedPcDescriptors); }
  static intptr_t UnroundedSize(PcDescriptorsPtr desc) {
    return UnroundedSize(desc->untag()->length_);
  }
  static intptr_t UnroundedSize(intptr_t len) { return HeaderSize() + len; }
  static intptr_t InstanceSize() {
    ASSERT_EQUAL(sizeof(UntaggedPcDescriptors),
                 OFFSET_OF_RETURNED_VALUE(UntaggedPcDescriptors, data));
    return 0;
  }
  static intptr_t InstanceSize(intptr_t len) {
    ASSERT(0 <= len && len <= kMaxElements);
    return RoundedAllocationSize(UnroundedSize(len));
  }

  static PcDescriptorsPtr New(const void* delta_encoded_data, intptr_t size);

  // Verify (assert) assumptions about pc descriptors in debug mode.
  void Verify(const Function& function) const;

  static void PrintHeaderString();

  void PrintToJSONObject(JSONObject* jsobj, bool ref) const;

  // We would have a VisitPointers function here to traverse the
  // pc descriptors table to visit objects if any in the table.
  // Note: never return a reference to a UntaggedPcDescriptors::PcDescriptorRec
  // as the object can move.
  class Iterator : public ValueObject {
   public:
    Iterator(const PcDescriptors& descriptors, intptr_t kind_mask)
        : descriptors_(descriptors),
          kind_mask_(kind_mask),
          byte_index_(0),
          cur_pc_offset_(0),
          cur_kind_(0),
          cur_deopt_id_(0),
          cur_token_pos_(0),
          cur_try_index_(0),
          cur_yield_index_(UntaggedPcDescriptors::kInvalidYieldIndex) {}

    bool MoveNext() {
      NoSafepointScope scope;
      ReadStream stream(descriptors_.untag()->data(), descriptors_.Length(),
                        byte_index_);
      // Moves to record that matches kind_mask_.
      while (byte_index_ < descriptors_.Length()) {
        const int32_t kind_and_metadata = stream.ReadSLEB128<int32_t>();
        cur_kind_ = UntaggedPcDescriptors::KindAndMetadata::DecodeKind(
            kind_and_metadata);
        cur_try_index_ = UntaggedPcDescriptors::KindAndMetadata::DecodeTryIndex(
            kind_and_metadata);
        cur_yield_index_ =
            UntaggedPcDescriptors::KindAndMetadata::DecodeYieldIndex(
                kind_and_metadata);

        cur_pc_offset_ += stream.ReadSLEB128();

        if (!FLAG_precompiled_mode) {
          cur_deopt_id_ += stream.ReadSLEB128();
          cur_token_pos_ = Utils::AddWithWrapAround(
              cur_token_pos_, stream.ReadSLEB128<int32_t>());
        }
        byte_index_ = stream.Position();

        if ((cur_kind_ & kind_mask_) != 0) {
          return true;  // Current is valid.
        }
      }
      return false;
    }

    uword PcOffset() const { return cur_pc_offset_; }
    intptr_t DeoptId() const { return cur_deopt_id_; }
    TokenPosition TokenPos() const {
      return TokenPosition::Deserialize(cur_token_pos_);
    }
    intptr_t TryIndex() const { return cur_try_index_; }
    intptr_t YieldIndex() const { return cur_yield_index_; }
    UntaggedPcDescriptors::Kind Kind() const {
      return static_cast<UntaggedPcDescriptors::Kind>(cur_kind_);
    }

   private:
    friend class PcDescriptors;

    // For nested iterations, starting at element after.
    explicit Iterator(const Iterator& iter)
        : ValueObject(),
          descriptors_(iter.descriptors_),
          kind_mask_(iter.kind_mask_),
          byte_index_(iter.byte_index_),
          cur_pc_offset_(iter.cur_pc_offset_),
          cur_kind_(iter.cur_kind_),
          cur_deopt_id_(iter.cur_deopt_id_),
          cur_token_pos_(iter.cur_token_pos_),
          cur_try_index_(iter.cur_try_index_),
          cur_yield_index_(iter.cur_yield_index_) {}

    const PcDescriptors& descriptors_;
    const intptr_t kind_mask_;
    intptr_t byte_index_;

    intptr_t cur_pc_offset_;
    intptr_t cur_kind_;
    intptr_t cur_deopt_id_;
    int32_t cur_token_pos_;
    intptr_t cur_try_index_;
    intptr_t cur_yield_index_;
  };

  intptr_t Length() const;
  bool Equals(const PcDescriptors& other) const {
    if (Length() != other.Length()) {
      return false;
    }
    NoSafepointScope no_safepoint;
    return memcmp(untag(), other.untag(), InstanceSize(Length())) == 0;
  }

 private:
  static const char* KindAsStr(UntaggedPcDescriptors::Kind kind);

  static PcDescriptorsPtr New(intptr_t length);

  void SetLength(intptr_t value) const;
  void CopyData(const void* bytes, intptr_t size);

  FINAL_HEAP_OBJECT_IMPLEMENTATION(PcDescriptors, Object);
  friend class Class;
  friend class Object;
};

class CodeSourceMap : public Object {
 public:
  static const intptr_t kBytesPerElement = 1;
  static const intptr_t kMaxElements = kMaxInt32 / kBytesPerElement;

  static intptr_t HeaderSize() { return sizeof(UntaggedCodeSourceMap); }
  static intptr_t UnroundedSize(CodeSourceMapPtr map) {
    return UnroundedSize(map->untag()->length_);
  }
  static intptr_t UnroundedSize(intptr_t len) { return HeaderSize() + len; }
  static intptr_t InstanceSize() {
    ASSERT_EQUAL(sizeof(UntaggedCodeSourceMap),
                 OFFSET_OF_RETURNED_VALUE(UntaggedCodeSourceMap, data));
    return 0;
  }
  static intptr_t InstanceSize(intptr_t len) {
    ASSERT(0 <= len && len <= kMaxElements);
    return RoundedAllocationSize(UnroundedSize(len));
  }

  static CodeSourceMapPtr New(intptr_t length);

  intptr_t Length() const { return untag()->length_; }
  uint8_t* Data() const { return UnsafeMutableNonPointer(&untag()->data()[0]); }

  bool Equals(const CodeSourceMap& other) const {
    if (Length() != other.Length()) {
      return false;
    }
    NoSafepointScope no_safepoint;
    return memcmp(untag(), other.untag(), InstanceSize(Length())) == 0;
  }

  uint32_t Hash() const {
    NoSafepointScope no_safepoint;
    return HashBytes(Data(), Length());
  }

  void PrintToJSONObject(JSONObject* jsobj, bool ref) const;

 private:
  void SetLength(intptr_t value) const;

  FINAL_HEAP_OBJECT_IMPLEMENTATION(CodeSourceMap, Object);
  friend class Class;
  friend class Object;
};

class CompressedStackMaps : public Object {
 public:
  uintptr_t payload_size() const { return PayloadSizeOf(ptr()); }
  static uintptr_t PayloadSizeOf(const CompressedStackMapsPtr raw) {
    return UntaggedCompressedStackMaps::SizeField::decode(
        raw->untag()->payload()->flags_and_size());
  }

  const uint8_t* data() const { return ptr()->untag()->payload()->data(); }

  // Methods to allow use with PointerKeyValueTrait to create sets of CSMs.
  bool Equals(const CompressedStackMaps& other) const {
    // All of the table flags and payload size must match.
    if (untag()->payload()->flags_and_size() !=
        other.untag()->payload()->flags_and_size()) {
      return false;
    }
    NoSafepointScope no_safepoint;
    return memcmp(untag(), other.untag(), InstanceSize(payload_size())) == 0;
  }
  uword Hash() const;

  static intptr_t HeaderSize() {
    return sizeof(UntaggedCompressedStackMaps) +
           sizeof(UntaggedCompressedStackMaps::Payload::FlagsAndSizeHeader);
  }
  static intptr_t UnroundedSize(CompressedStackMapsPtr maps) {
    return UnroundedSize(CompressedStackMaps::PayloadSizeOf(maps));
  }
  static intptr_t UnroundedSize(intptr_t length) {
    return HeaderSize() + length;
  }
  static intptr_t InstanceSize() { return 0; }
  static intptr_t InstanceSize(intptr_t length) {
    return RoundedAllocationSize(UnroundedSize(length));
  }

  bool UsesGlobalTable() const { return UsesGlobalTable(ptr()); }
  static bool UsesGlobalTable(const CompressedStackMapsPtr raw) {
    return UntaggedCompressedStackMaps::UsesTableBit::decode(
        raw->untag()->payload()->flags_and_size());
  }

  bool IsGlobalTable() const { return IsGlobalTable(ptr()); }
  static bool IsGlobalTable(const CompressedStackMapsPtr raw) {
    return UntaggedCompressedStackMaps::GlobalTableBit::decode(
        raw->untag()->payload()->flags_and_size());
  }

  static CompressedStackMapsPtr NewInlined(const void* payload, intptr_t size) {
    return New(payload, size, /*is_global_table=*/false,
               /*uses_global_table=*/false);
  }
  static CompressedStackMapsPtr NewUsingTable(const void* payload,
                                              intptr_t size) {
    return New(payload, size, /*is_global_table=*/false,
               /*uses_global_table=*/true);
  }

  static CompressedStackMapsPtr NewGlobalTable(const void* payload,
                                               intptr_t size) {
    return New(payload, size, /*is_global_table=*/true,
               /*uses_global_table=*/false);
  }

  class RawPayloadHandle {
   public:
    RawPayloadHandle() {}
    RawPayloadHandle(const RawPayloadHandle&) = default;
    RawPayloadHandle& operator=(const RawPayloadHandle&) = default;

    const UntaggedCompressedStackMaps::Payload* payload() const {
      return payload_;
    }
    bool IsNull() const { return payload_ == nullptr; }

    RawPayloadHandle& operator=(
        const UntaggedCompressedStackMaps::Payload* payload) {
      payload_ = payload;
      return *this;
    }

    RawPayloadHandle& operator=(const CompressedStackMaps& maps) {
      ASSERT(!maps.IsNull());
      payload_ = maps.untag()->payload();
      return *this;
    }

    RawPayloadHandle& operator=(CompressedStackMapsPtr maps) {
      ASSERT(maps != CompressedStackMaps::null());
      payload_ = maps.untag()->payload();
      return *this;
    }

    uintptr_t payload_size() const {
      return UntaggedCompressedStackMaps::SizeField::decode(
          payload()->flags_and_size());
    }
    const uint8_t* data() const { return payload()->data(); }

    bool UsesGlobalTable() const {
      return UntaggedCompressedStackMaps::UsesTableBit::decode(
          payload()->flags_and_size());
    }

    bool IsGlobalTable() const {
      return UntaggedCompressedStackMaps::GlobalTableBit::decode(
          payload()->flags_and_size());
    }

   private:
    const UntaggedCompressedStackMaps::Payload* payload_ = nullptr;
  };

  template <typename PayloadHandle>
  class Iterator {
   public:
    Iterator(const PayloadHandle& maps, const PayloadHandle& global_table)
        : maps_(maps),
          bits_container_(maps.UsesGlobalTable() ? global_table : maps) {
      ASSERT(!maps_.IsNull());
      ASSERT(!bits_container_.IsNull());
      ASSERT(!maps_.IsGlobalTable());
      ASSERT(!maps_.UsesGlobalTable() || bits_container_.IsGlobalTable());
    }

    Iterator(const Iterator& it)
        : maps_(it.maps_),
          bits_container_(it.bits_container_),
          next_offset_(it.next_offset_),
          current_pc_offset_(it.current_pc_offset_),
          current_global_table_offset_(it.current_global_table_offset_),
          current_spill_slot_bit_count_(it.current_spill_slot_bit_count_),
          current_non_spill_slot_bit_count_(it.current_spill_slot_bit_count_),
          current_bits_offset_(it.current_bits_offset_) {}

    // Loads the next entry from [maps_], if any. If [maps_] is the null value,
    // this always returns false.
    bool MoveNext() {
      if (next_offset_ >= maps_.payload_size()) {
        return false;
      }

      NoSafepointScope scope;
      ReadStream stream(maps_.data(), maps_.payload_size(), next_offset_);

      auto const pc_delta = stream.ReadLEB128();
      ASSERT(pc_delta <= (kMaxUint32 - current_pc_offset_));
      current_pc_offset_ += pc_delta;

      // Table-using CSMs have a table offset after the PC offset delta, whereas
      // the post-delta part of inlined entries has the same information as
      // global table entries.
      // See comments in UntaggedCompressedStackMaps for description of
      // encoding.
      if (maps_.UsesGlobalTable()) {
        current_global_table_offset_ = stream.ReadLEB128();
        ASSERT(current_global_table_offset_ < bits_container_.payload_size());

        // Since generally we only use entries in the GC and the GC only needs
        // the rest of the entry information if the PC offset matches, we lazily
        // load and cache the information stored in the global object when it is
        // actually requested.
        current_spill_slot_bit_count_ = -1;
        current_non_spill_slot_bit_count_ = -1;
        current_bits_offset_ = -1;

        next_offset_ = stream.Position();
      } else {
        current_spill_slot_bit_count_ = stream.ReadLEB128();
        ASSERT(current_spill_slot_bit_count_ >= 0);

        current_non_spill_slot_bit_count_ = stream.ReadLEB128();
        ASSERT(current_non_spill_slot_bit_count_ >= 0);

        const auto stackmap_bits =
            current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
        const uintptr_t stackmap_size =
            Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
        ASSERT(stackmap_size <= (maps_.payload_size() - stream.Position()));

        current_bits_offset_ = stream.Position();
        next_offset_ = current_bits_offset_ + stackmap_size;
      }

      return true;
    }

    // Finds the entry with the given PC offset starting at the current position
    // of the iterator. If [maps_] is the null value, this always returns false.
    bool Find(uint32_t pc_offset) {
      // We should never have an entry with a PC offset of 0 inside an
      // non-empty CSM, so fail.
      if (pc_offset == 0) return false;
      do {
        if (current_pc_offset_ >= pc_offset) break;
      } while (MoveNext());
      return current_pc_offset_ == pc_offset;
    }

    // Methods for accessing parts of an entry should not be called until
    // a successful MoveNext() or Find() call has been made.

    // Returns the PC offset of the loaded entry.
    uint32_t pc_offset() const {
      ASSERT(HasLoadedEntry());
      return current_pc_offset_;
    }

    // Returns the bit length of the loaded entry.
    intptr_t Length() const {
      EnsureFullyLoadedEntry();
      return current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
    }
    // Returns the number of spill slot bits of the loaded entry.
    intptr_t SpillSlotBitCount() const {
      EnsureFullyLoadedEntry();
      return current_spill_slot_bit_count_;
    }
    // Returns whether the stack entry represented by the offset contains
    // a tagged object.
    bool IsObject(intptr_t bit_index) const {
      EnsureFullyLoadedEntry();
      ASSERT(bit_index >= 0 && bit_index < Length());
      const intptr_t byte_index = bit_index >> kBitsPerByteLog2;
      const intptr_t bit_remainder = bit_index & (kBitsPerByte - 1);
      uint8_t byte_mask = 1U << bit_remainder;
      const intptr_t byte_offset = current_bits_offset_ + byte_index;
      NoSafepointScope scope;
      return (bits_container_.data()[byte_offset] & byte_mask) != 0;
    }

   private:
    bool HasLoadedEntry() const { return next_offset_ > 0; }

    // Caches the corresponding values from the global table in the mutable
    // fields. We lazily load these as some clients only need the PC offset.
    void LazyLoadGlobalTableEntry() const {
      ASSERT(maps_.UsesGlobalTable());
      ASSERT(HasLoadedEntry());
      ASSERT(current_global_table_offset_ < bits_container_.payload_size());

      NoSafepointScope scope;
      ReadStream stream(bits_container_.data(), bits_container_.payload_size(),
                        current_global_table_offset_);

      current_spill_slot_bit_count_ = stream.ReadLEB128();
      ASSERT(current_spill_slot_bit_count_ >= 0);

      current_non_spill_slot_bit_count_ = stream.ReadLEB128();
      ASSERT(current_non_spill_slot_bit_count_ >= 0);

      const auto stackmap_bits = Length();
      const uintptr_t stackmap_size =
          Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
      ASSERT(stackmap_size <=
             (bits_container_.payload_size() - stream.Position()));

      current_bits_offset_ = stream.Position();
    }

    void EnsureFullyLoadedEntry() const {
      ASSERT(HasLoadedEntry());
      if (current_spill_slot_bit_count_ < 0) {
        LazyLoadGlobalTableEntry();
        ASSERT(current_spill_slot_bit_count_ >= 0);
      }
    }

    const PayloadHandle& maps_;
    const PayloadHandle& bits_container_;

    uintptr_t next_offset_ = 0;
    uint32_t current_pc_offset_ = 0;
    // Only used when looking up non-PC information in the global table.
    uintptr_t current_global_table_offset_ = 0;
    // Marked as mutable as these fields may be updated with lazily loaded
    // values from the global table when their associated accessor is called,
    // but those values will never change for a given entry once loaded..
    mutable intptr_t current_spill_slot_bit_count_ = -1;
    mutable intptr_t current_non_spill_slot_bit_count_ = -1;
    mutable intptr_t current_bits_offset_ = -1;

    friend class StackMapEntry;
  };

  Iterator<CompressedStackMaps> iterator(Thread* thread) const;

  void WriteToBuffer(BaseTextBuffer* buffer, const char* separator) const;

 private:
  static CompressedStackMapsPtr New(const void* payload,
                                    intptr_t size,
                                    bool is_global_table,
                                    bool uses_global_table);

  FINAL_HEAP_OBJECT_IMPLEMENTATION(CompressedStackMaps, Object);
  friend class Class;
};

class ExceptionHandlers : public Object {
 public:
  static const intptr_t kInvalidPcOffset = 0;

  intptr_t num_entries() const;

  void GetHandlerInfo(intptr_t try_index, ExceptionHandlerInfo* info) const;

  uword HandlerPCOffset(intptr_t try_index) const;
  intptr_t OuterTryIndex(intptr_t try_index) const;
  bool NeedsStackTrace(intptr_t try_index) const;
  bool IsGenerated(intptr_t try_index) const;

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

  ArrayPtr GetHandledTypes(intptr_t try_index) const;
  void SetHandledTypes(intptr_t try_index, const Array& handled_types) const;
  bool HasCatchAll(intptr_t try_index) const;

  struct ArrayTraits {
    static intptr_t elements_start_offset() {
      return sizeof(UntaggedExceptionHandlers);
    }
    static constexpr intptr_t kElementSize = sizeof(ExceptionHandlerInfo);
  };

  static intptr_t InstanceSize() {
    ASSERT(sizeof(UntaggedExceptionHandlers) ==
           OFFSET_OF_RETURNED_VALUE(UntaggedExceptionHandlers, data));
    return 0;
  }
  static intptr_t InstanceSize(intptr_t len) {
    return RoundedAllocationSize(sizeof(UntaggedExceptionHandlers) +
                                 (len * sizeof(ExceptionHandlerInfo)));
  }

  static ExceptionHandlersPtr New(intptr_t num_handlers);
  static ExceptionHandlersPtr New(const Array& handled_types_data);

  // We would have a VisitPointers function here to traverse the
  // exception handler table to visit objects if any in the table.

 private:
  // Pick somewhat arbitrary maximum number of exception handlers
  // for a function. This value is used to catch potentially
  // malicious code.
  static const intptr_t kMaxHandlers = 1024 * 1024;

  void set_handled_types_data(const Array& value) const;

  FINAL_HEAP_OBJECT_IMPLEMENTATION(ExceptionHandlers, Object);
  friend class Class;
  friend class Object;
};

// A WeakSerializationReference (WSR) denotes a type of weak reference to a
// target object. In particular, objects that can only be reached from roots via
// WSR edges during serialization of AOT snapshots should not be serialized, but
// instead references to these objects should be replaced with a reference to
// the provided replacement object.
//
// Of course, the target object may still be serialized if there are paths to
// the object from the roots that do not go through one of these objects. In
// this case, references through WSRs are serialized as direct references to
// the target.
//
// Unfortunately a WSR is not a proxy for the original object, so WSRs may
// only currently be used with ObjectPtr fields. To ease this situation for
// fields that are normally a non-ObjectPtr type outside of the precompiler,
// use the following macros, which avoid the need to adjust other code to
// handle the WSR case:
//
// * WSR_*POINTER_FIELD() in raw_object.h (i.e., just append WSR_ to the
//   original field declaration).
// * PRECOMPILER_WSR_FIELD_DECLARATION() in object.h
// * PRECOMPILER_WSR_FIELD_DEFINITION() in object.cc
class WeakSerializationReference : public Object {
 public:
  ObjectPtr target() const { return TargetOf(ptr()); }
  static ObjectPtr TargetOf(const WeakSerializationReferencePtr obj) {
    return obj->untag()->target();
  }

  static ObjectPtr Unwrap(ObjectPtr obj) {
#if defined(DART_PRECOMPILER)
    if (obj->IsHeapObject() && obj->IsWeakSerializationReference()) {
      return TargetOf(static_cast<WeakSerializationReferencePtr>(obj));
    }
#endif
    return obj;
  }
  static ObjectPtr Unwrap(const Object& obj) { return Unwrap(obj.ptr()); }
  static ObjectPtr UnwrapIfTarget(ObjectPtr obj) { return Unwrap(obj); }
  static ObjectPtr UnwrapIfTarget(const Object& obj) { return Unwrap(obj); }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedWeakSerializationReference));
  }

  // Returns an ObjectPtr as the target may not need wrapping (e.g., it
  // is guaranteed to be serialized).
  static ObjectPtr New(const Object& target, const Object& replacement);

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(WeakSerializationReference, Object);

  ObjectPtr replacement() const { return untag()->replacement(); }

  friend class Class;
};

class Code : public Object {
 public:
  // When dual mapping, this returns the executable view.
  InstructionsPtr active_instructions() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
    return NULL;
#else
    return untag()->active_instructions();
#endif
  }

  // When dual mapping, these return the executable view.
  InstructionsPtr instructions() const { return untag()->instructions(); }
  static InstructionsPtr InstructionsOf(const CodePtr code) {
    return code->untag()->instructions();
  }

  static intptr_t saved_instructions_offset() {
    return OFFSET_OF(UntaggedCode, instructions_);
  }

  using EntryKind = CodeEntryKind;

  static const char* EntryKindToCString(EntryKind kind);
  static bool ParseEntryKind(const char* str, EntryKind* out);

  static intptr_t entry_point_offset(EntryKind kind = EntryKind::kNormal) {
    switch (kind) {
      case EntryKind::kNormal:
        return OFFSET_OF(UntaggedCode, entry_point_);
      case EntryKind::kUnchecked:
        return OFFSET_OF(UntaggedCode, unchecked_entry_point_);
      case EntryKind::kMonomorphic:
        return OFFSET_OF(UntaggedCode, monomorphic_entry_point_);
      case EntryKind::kMonomorphicUnchecked:
        return OFFSET_OF(UntaggedCode, monomorphic_unchecked_entry_point_);
      default:
        UNREACHABLE();
    }
  }

  ObjectPoolPtr object_pool() const { return untag()->object_pool(); }
  static intptr_t object_pool_offset() {
    return OFFSET_OF(UntaggedCode, object_pool_);
  }

  intptr_t pointer_offsets_length() const {
    return PtrOffBits::decode(untag()->state_bits_);
  }

  bool is_optimized() const {
    return OptimizedBit::decode(untag()->state_bits_);
  }
  void set_is_optimized(bool value) const;
  static bool IsOptimized(CodePtr code) {
    return Code::OptimizedBit::decode(code->untag()->state_bits_);
  }

  bool is_force_optimized() const {
    return ForceOptimizedBit::decode(untag()->state_bits_);
  }
  void set_is_force_optimized(bool value) const;

  bool is_alive() const { return AliveBit::decode(untag()->state_bits_); }
  void set_is_alive(bool value) const;

  bool is_discarded() const { return IsDiscarded(ptr()); }
  static bool IsDiscarded(const CodePtr code) {
    return DiscardedBit::decode(code->untag()->state_bits_);
  }
  void set_is_discarded(bool value) const;

  bool HasMonomorphicEntry() const { return HasMonomorphicEntry(ptr()); }
  static bool HasMonomorphicEntry(const CodePtr code) {
#if defined(DART_PRECOMPILED_RUNTIME)
    return code->untag()->entry_point_ !=
           code->untag()->monomorphic_entry_point_;
#else
    return Instructions::HasMonomorphicEntry(InstructionsOf(code));
#endif
  }

  // Returns the payload start of [instructions()].
  uword PayloadStart() const { return PayloadStartOf(ptr()); }
  static uword PayloadStartOf(const CodePtr code) {
#if defined(DART_PRECOMPILED_RUNTIME)
    if (IsUnknownDartCode(code)) return 0;
    const uword entry_offset = HasMonomorphicEntry(code)
                                   ? Instructions::kPolymorphicEntryOffsetAOT
                                   : 0;
    return EntryPointOf(code) - entry_offset;
#else
    return Instructions::PayloadStart(InstructionsOf(code));
#endif
  }

  // Returns the entry point of [instructions()].
  uword EntryPoint() const { return EntryPointOf(ptr()); }
  static uword EntryPointOf(const CodePtr code) {
#if defined(DART_PRECOMPILED_RUNTIME)
    return code->untag()->entry_point_;
#else
    return Instructions::EntryPoint(InstructionsOf(code));
#endif
  }

  static uword UncheckedEntryPointOf(const CodePtr code) {
    return code->untag()->unchecked_entry_point_;
  }

  // Returns the unchecked entry point of [instructions()].
  uword UncheckedEntryPoint() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    return untag()->unchecked_entry_point_;
#else
    return EntryPoint() + untag()->unchecked_offset_;
#endif
  }
  // Returns the monomorphic entry point of [instructions()].
  uword MonomorphicEntryPoint() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    return untag()->monomorphic_entry_point_;
#else
    return Instructions::MonomorphicEntryPoint(instructions());
#endif
  }
  // Returns the unchecked monomorphic entry point of [instructions()].
  uword MonomorphicUncheckedEntryPoint() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    return untag()->monomorphic_unchecked_entry_point_;
#else
    return MonomorphicEntryPoint() + untag()->unchecked_offset_;
#endif
  }

  // Returns the size of [instructions()].
  uword Size() const { return PayloadSizeOf(ptr()); }
  static uword PayloadSizeOf(const CodePtr code) {
#if defined(DART_PRECOMPILED_RUNTIME)
    if (IsUnknownDartCode(code)) return kUwordMax;
    return code->untag()->instructions_length_;
#else
    return Instructions::Size(InstructionsOf(code));
#endif
  }

  ObjectPoolPtr GetObjectPool() const;
  // Returns whether the given PC address is in [instructions()].
  bool ContainsInstructionAt(uword addr) const {
    return ContainsInstructionAt(ptr(), addr);
  }

  // Returns whether the given PC address is in [InstructionsOf(code)].
  static bool ContainsInstructionAt(const CodePtr code, uword pc) {
    return UntaggedCode::ContainsPC(code, pc);
  }

  // Returns true if there is a debugger breakpoint set in this code object.
  bool HasBreakpoint() const;

  PcDescriptorsPtr pc_descriptors() const { return untag()->pc_descriptors(); }
  void set_pc_descriptors(const PcDescriptors& descriptors) const {
    ASSERT(descriptors.IsOld());
    untag()->set_pc_descriptors(descriptors.ptr());
  }

  CodeSourceMapPtr code_source_map() const {
    return untag()->code_source_map();
  }

  void set_code_source_map(const CodeSourceMap& code_source_map) const {
    ASSERT(code_source_map.IsOld());
    untag()->set_code_source_map(code_source_map.ptr());
  }

  // Array of DeoptInfo objects.
  ArrayPtr deopt_info_array() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
    return NULL;
#else
    return untag()->deopt_info_array();
#endif
  }
  void set_deopt_info_array(const Array& array) const;

#if !defined(DART_PRECOMPILED_RUNTIME)
  intptr_t num_variables() const;
  void set_num_variables(intptr_t num_variables) const;
#endif

#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
  TypedDataPtr catch_entry_moves_maps() const;
  void set_catch_entry_moves_maps(const TypedData& maps) const;
#endif

  CompressedStackMapsPtr compressed_stackmaps() const {
    return untag()->compressed_stackmaps();
  }
  void set_compressed_stackmaps(const CompressedStackMaps& maps) const;

  enum CallKind {
    kPcRelativeCall = 1,
    kPcRelativeTTSCall = 2,
    kPcRelativeTailCall = 3,
    kCallViaCode = 4,
  };

  enum CallEntryPoint {
    kDefaultEntry,
    kUncheckedEntry,
  };

  enum SCallTableEntry {
    kSCallTableKindAndOffset = 0,
    kSCallTableCodeOrTypeTarget = 1,
    kSCallTableFunctionTarget = 2,
    kSCallTableEntryLength = 3,
  };

  enum class PoolAttachment {
    kAttachPool,
    kNotAttachPool,
  };

  class KindField : public BitField<intptr_t, CallKind, 0, 3> {};
  class EntryPointField
      : public BitField<intptr_t, CallEntryPoint, KindField::kNextBit, 1> {};
  class OffsetField
      : public BitField<intptr_t, intptr_t, EntryPointField::kNextBit, 26> {};

  void set_static_calls_target_table(const Array& value) const;
  ArrayPtr static_calls_target_table() const {
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
    return NULL;
#else
    return untag()->static_calls_target_table();
#endif
  }

  TypedDataPtr GetDeoptInfoAtPc(uword pc,
                                ICData::DeoptReasonId* deopt_reason,
                                uint32_t* deopt_flags) const;

  // Returns null if there is no static call at 'pc'.
  FunctionPtr GetStaticCallTargetFunctionAt(uword pc) const;
  // Aborts if there is no static call at 'pc'.
  void SetStaticCallTargetCodeAt(uword pc, const Code& code) const;
  void SetStubCallTargetCodeAt(uword pc, const Code& code) const;

  void Disassemble(DisassemblyFormatter* formatter = NULL) const;

#if defined(INCLUDE_IL_PRINTER)
  class Comments : public ZoneAllocated, public CodeComments {
   public:
    static Comments& New(intptr_t count);

    intptr_t Length() const override;

    void SetPCOffsetAt(intptr_t idx, intptr_t pc_offset);
    void SetCommentAt(intptr_t idx, const String& comment);

    intptr_t PCOffsetAt(intptr_t idx) const override;
    const char* CommentAt(intptr_t idx) const override;

   private:
    explicit Comments(const Array& comments);

    // Layout of entries describing comments.
    enum {kPCOffsetEntry = 0,  // PC offset to a comment as a Smi.
          kCommentEntry,       // Comment text as a String.
          kNumberOfEntries};

    const Array& comments_;
    String& string_;

    friend class Code;

    DISALLOW_COPY_AND_ASSIGN(Comments);
  };

  const CodeComments& comments() const;
  void set_comments(const CodeComments& comments) const;
#endif  // defined(INCLUDE_IL_PRINTER)

  ObjectPtr return_address_metadata() const {
#if defined(PRODUCT)
    UNREACHABLE();
    return NULL;
#else
    return untag()->return_address_metadata();
#endif
  }
  // Sets |return_address_metadata|.
  void SetPrologueOffset(intptr_t offset) const;
  // Returns -1 if no prologue offset is available.
  intptr_t GetPrologueOffset() const;

  ArrayPtr inlined_id_to_function() const;
  void set_inlined_id_to_function(const Array& value) const;

  // Provides the call stack at the given pc offset, with the top-of-stack in
  // the last element and the root function (this) as the first element, along
  // with the corresponding source positions. Note the token position for each
  // function except the top-of-stack is the position of the call to the next
  // function. The stack will be empty if we lack the metadata to produce it,
  // which happens for stub code.
  // The pc offset is interpreted as an instruction address (as needed by the
  // disassembler or the top frame of a profiler sample).
  void GetInlinedFunctionsAtInstruction(
      intptr_t pc_offset,
      GrowableArray<const Function*>* functions,
      GrowableArray<TokenPosition>* token_positions) const;
  // Same as above, except the pc is interpreted as a return address (as needed
  // for a stack trace or the bottom frames of a profiler sample).
  void GetInlinedFunctionsAtReturnAddress(
      intptr_t pc_offset,
      GrowableArray<const Function*>* functions,
      GrowableArray<TokenPosition>* token_positions) const {
    GetInlinedFunctionsAtInstruction(pc_offset - 1, functions, token_positions);
  }

  NOT_IN_PRODUCT(void PrintJSONInlineIntervals(JSONObject* object) const);
  void DumpInlineIntervals() const;
  void DumpSourcePositions(bool relative_addresses = false) const;

  LocalVarDescriptorsPtr var_descriptors() const {
#if defined(PRODUCT)
    UNREACHABLE();
    return NULL;
#else
    return untag()->var_descriptors();
#endif
  }
  void set_var_descriptors(const LocalVarDescriptors& value) const {
#if defined(PRODUCT)
    UNREACHABLE();
#else
    ASSERT(value.IsOld());
    untag()->set_var_descriptors(value.ptr());
#endif
  }

  // Will compute local var descriptors if necessary.
  LocalVarDescriptorsPtr GetLocalVarDescriptors() const;

  ExceptionHandlersPtr exception_handlers() const {
    return untag()->exception_handlers();
  }
  void set_exception_handlers(const ExceptionHandlers& handlers) const {
    ASSERT(handlers.IsOld());
    untag()->set_exception_handlers(handlers.ptr());
  }

  // WARNING: function() returns the owner which is not guaranteed to be
  // a Function. It is up to the caller to guarantee it isn't a stub, class,
  // or something else.
  // TODO(turnidge): Consider dropping this function and making
  // everybody use owner().  Currently this function is misused - even
  // while generating the snapshot.
  FunctionPtr function() const {
    ASSERT(IsFunctionCode());
    return Function::RawCast(owner());
  }

  ObjectPtr owner() const {
    return WeakSerializationReference::Unwrap(untag()->owner());
  }
  void set_owner(const Object& owner) const;

  classid_t OwnerClassId() const { return OwnerClassIdOf(ptr()); }
  static classid_t OwnerClassIdOf(CodePtr raw) {
    ObjectPtr owner = WeakSerializationReference::Unwrap(raw->untag()->owner());
    if (!owner->IsHeapObject()) {
      return RawSmiValue(static_cast<SmiPtr>(owner));
    }
    return owner->GetClassId();
  }

  static intptr_t owner_offset() { return OFFSET_OF(UntaggedCode, owner_); }

  // We would have a VisitPointers function here to traverse all the
  // embedded objects in the instructions using pointer_offsets.

  static const intptr_t kBytesPerElement =
      sizeof(reinterpret_cast<UntaggedCode*>(kOffsetOfPtr)->data()[0]);
  static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;

  struct ArrayTraits {
    static intptr_t elements_start_offset() { return sizeof(UntaggedCode); }
    static constexpr intptr_t kElementSize = kBytesPerElement;
  };

  static intptr_t InstanceSize() {
    ASSERT(sizeof(UntaggedCode) ==
           OFFSET_OF_RETURNED_VALUE(UntaggedCode, data));
    return 0;
  }
  static intptr_t InstanceSize(intptr_t len) {
    ASSERT(0 <= len && len <= kMaxElements);
    return RoundedAllocationSize(sizeof(UntaggedCode) +
                                 (len * kBytesPerElement));
  }
#if !defined(DART_PRECOMPILED_RUNTIME)
  // Finalizes the generated code, by generating various kinds of metadata (e.g.
  // stack maps, pc descriptors, ...) and attach them to a newly generated
  // [Code] object.
  //
  // If Code::PoolAttachment::kAttachPool is specified for [pool_attachment]
  // then a new [ObjectPool] will be attached to the code object as well.
  // Otherwise the caller is responsible for doing this via
  // `Object::set_object_pool()`.
  static CodePtr FinalizeCode(FlowGraphCompiler* compiler,
                              compiler::Assembler* assembler,
                              PoolAttachment pool_attachment,
                              bool optimized,
                              CodeStatistics* stats);

  // Notifies all active [CodeObserver]s.
  static void NotifyCodeObservers(const Code& code, bool optimized);
  static void NotifyCodeObservers(const Function& function,
                                  const Code& code,
                                  bool optimized);
  static void NotifyCodeObservers(const char* name,
                                  const Code& code,
                                  bool optimized);

  // Calls [FinalizeCode] and also notifies [CodeObserver]s.
  static CodePtr FinalizeCodeAndNotify(const Function& function,
                                       FlowGraphCompiler* compiler,
                                       compiler::Assembler* assembler,
                                       PoolAttachment pool_attachment,
                                       bool optimized = false,
                                       CodeStatistics* stats = nullptr);
  static CodePtr FinalizeCodeAndNotify(const char* name,
                                       FlowGraphCompiler* compiler,
                                       compiler::Assembler* assembler,
                                       PoolAttachment pool_attachment,
                                       bool optimized = false,
                                       CodeStatistics* stats = nullptr);

#endif
  static CodePtr LookupCode(uword pc);
  static CodePtr LookupCodeInVmIsolate(uword pc);
  static CodePtr FindCode(uword pc, int64_t timestamp);

  int32_t GetPointerOffsetAt(int index) const {
    NoSafepointScope no_safepoint;
    return *PointerOffsetAddrAt(index);
  }
  TokenPosition GetTokenIndexOfPC(uword pc) const;

  // Find pc, return 0 if not found.
  uword GetPcForDeoptId(intptr_t deopt_id,
                        UntaggedPcDescriptors::Kind kind) const;
  intptr_t GetDeoptIdForOsr(uword pc) const;

  const char* Name() const;
  const char* QualifiedName(const NameFormattingParams& params) const;

  int64_t compile_timestamp() const {
#if defined(PRODUCT)
    return 0;
#else
    return untag()->compile_timestamp_;
#endif
  }

  bool IsStubCode() const;
  bool IsAllocationStubCode() const;
  bool IsTypeTestStubCode() const;
  bool IsFunctionCode() const;

  // Returns true if this Code object represents
  // Dart function code without any additional information.
  bool IsUnknownDartCode() const { return IsUnknownDartCode(ptr()); }
  static bool IsUnknownDartCode(CodePtr code);

  void DisableDartCode() const;

  void DisableStubCode() const;

  void Enable() const {
    if (!IsDisabled()) return;
    ResetActiveInstructions();
  }

  bool IsDisabled() const { return IsDisabled(ptr()); }
  static bool IsDisabled(CodePtr code) {
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
    return false;
#else
    return code->untag()->instructions() !=
           code->untag()->active_instructions();
#endif
  }

  void set_object_pool(ObjectPoolPtr object_pool) const {
    untag()->set_object_pool(object_pool);
  }

 private:
  void set_state_bits(intptr_t bits) const;

  friend class UntaggedObject;  // For UntaggedObject::SizeFromClass().
  friend class UntaggedCode;
  friend struct RelocatorTestHelper;

  enum {
    kOptimizedBit = 0,
    kForceOptimizedBit = 1,
    kAliveBit = 2,
    kDiscardedBit = 3,
    kPtrOffBit = 4,
    kPtrOffSize = kBitsPerInt32 - kPtrOffBit,
  };

  class OptimizedBit : public BitField<int32_t, bool, kOptimizedBit, 1> {};

  // Force-optimized is true if the Code was generated for a function with
  // Function::ForceOptimize().
  class ForceOptimizedBit
      : public BitField<int32_t, bool, kForceOptimizedBit, 1> {};

  class AliveBit : public BitField<int32_t, bool, kAliveBit, 1> {};

  // Set by precompiler if this Code object doesn't contain
  // useful information besides instructions and compressed stack map.
  // Such objects are serialized in a shorter form and replaced with
  // StubCode::UnknownDartCode() during snapshot deserialization.
  class DiscardedBit : public BitField<int32_t, bool, kDiscardedBit, 1> {};

  class PtrOffBits
      : public BitField<int32_t, intptr_t, kPtrOffBit, kPtrOffSize> {};

  class SlowFindRawCodeVisitor : public FindObjectVisitor {
   public:
    explicit SlowFindRawCodeVisitor(uword pc) : pc_(pc) {}
    virtual ~SlowFindRawCodeVisitor() {}

    // Check if object matches find condition.
    virtual bool FindObject(ObjectPtr obj) const;

   private:
    const uword pc_;

    DISALLOW_COPY_AND_ASSIGN(SlowFindRawCodeVisitor);
  };

  static const intptr_t kEntrySize = sizeof(int32_t);  // NOLINT

  void set_compile_timestamp(int64_t timestamp) const {
#if defined(PRODUCT)
    UNREACHABLE();
#else
    StoreNonPointer(&untag()->compile_timestamp_, timestamp);
#endif
  }

  // Initializes the cached entrypoint addresses in [code] as calculated
  // from [instructions] and [unchecked_offset].
  static void InitializeCachedEntryPointsFrom(CodePtr code,
                                              InstructionsPtr instructions,
                                              uint32_t unchecked_offset);

  // Sets [active_instructions_] to [instructions] and updates the cached
  // entry point addresses.
  void SetActiveInstructions(const Instructions& instructions,
                             uint32_t unchecked_offset) const;
  void SetActiveInstructionsSafe(const Instructions& instructions,
                                 uint32_t unchecked_offset) const;

  // Resets [active_instructions_] to its original value of [instructions_] and
  // updates the cached entry point addresses to match.
  void ResetActiveInstructions() const;

  void set_instructions(const Instructions& instructions) const {
    ASSERT(Thread::Current()->IsMutatorThread() || !is_alive());
    untag()->set_instructions(instructions.ptr());
  }
#if !defined(DART_PRECOMPILED_RUNTIME)
  void set_unchecked_offset(uword offset) const {
    StoreNonPointer(&untag()->unchecked_offset_, offset);
  }
#endif

  // Returns the unchecked entry point offset for [instructions_].
  uint32_t UncheckedEntryPointOffset() const {
    return UncheckedEntryPointOffsetOf(ptr());
  }
  static uint32_t UncheckedEntryPointOffsetOf(CodePtr code) {
#if defined(DART_PRECOMPILED_RUNTIME)
    UNREACHABLE();
#else
    return code->untag()->unchecked_offset_;
#endif
  }

  void set_pointer_offsets_length(intptr_t value) {
    // The number of fixups is limited to 1-billion.
    ASSERT(Utils::IsUint(30, value));
    set_state_bits(PtrOffBits::update(value, untag()->state_bits_));
  }
  int32_t* PointerOffsetAddrAt(int index) const {
    ASSERT(index >= 0);
    ASSERT(index < pointer_offsets_length());
    // TODO(iposva): Unit test is missing for this functionality.
    return &UnsafeMutableNonPointer(untag()->data())[index];
  }
  void SetPointerOffsetAt(int index, int32_t offset_in_instructions) {
    NoSafepointScope no_safepoint;
    *PointerOffsetAddrAt(index) = offset_in_instructions;
  }

  intptr_t BinarySearchInSCallTable(uword pc) const;
  static CodePtr LookupCodeInIsolateGroup(IsolateGroup* isolate_group,
                                          uword pc);

  // New is a private method as RawInstruction and RawCode objects should
  // only be created using the Code::FinalizeCode method. This method creates
  // the RawInstruction and RawCode objects, sets up the pointer offsets
  // and links the two in a GC safe manner.
  static CodePtr New(intptr_t pointer_offsets_length);

  FINAL_HEAP_OBJECT_IMPLEMENTATION(Code, Object);
  friend class Class;
  friend class CodeTestHelper;
  friend class StubCode;     // for set_object_pool
  friend class Precompiler;  // for set_object_pool
  friend class FunctionSerializationCluster;
  friend class CodeSerializationCluster;
  friend class CodeDeserializationCluster;
  friend class Deserializer;           // for InitializeCachedEntryPointsFrom
  friend class StubCode;               // for set_object_pool
  friend class MegamorphicCacheTable;  // for set_object_pool
  friend class CodePatcher;            // for set_instructions
  friend class ProgramVisitor;         // for set_instructions
  // So that the UntaggedFunction pointer visitor can determine whether code the
  // function points to is optimized.
  friend class UntaggedFunction;
  friend class CallSiteResetter;
  friend class CodeKeyValueTrait;  // for UncheckedEntryPointOffset
};

class Context : public Object {
 public:
  ContextPtr parent() const { return untag()->parent(); }
  void set_parent(const Context& parent) const {
    untag()->set_parent(parent.ptr());
  }
  static intptr_t parent_offset() {
    return OFFSET_OF(UntaggedContext, parent_);
  }

  intptr_t num_variables() const { return untag()->num_variables_; }
  static intptr_t num_variables_offset() {
    return OFFSET_OF(UntaggedContext, num_variables_);
  }
  static intptr_t NumVariables(const ContextPtr context) {
    return context->untag()->num_variables_;
  }

  ObjectPtr At(intptr_t context_index) const {
    return untag()->element(context_index);
  }
  inline void SetAt(intptr_t context_index, const Object& value) const;

  intptr_t GetLevel() const;

  void Dump(int indent = 0) const;

  static const intptr_t kBytesPerElement = kCompressedWordSize;
  static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;

  static const intptr_t kAwaitJumpVarIndex = 0;
  static const intptr_t kAsyncFutureIndex = 1;
  static const intptr_t kControllerIndex = 1;
  // Expected context index of chained futures in recognized async functions.
  // These are used to unwind async stacks.
  static const intptr_t kIsSyncIndex = 2;

  struct ArrayTraits {
    static intptr_t elements_start_offset() { return sizeof(UntaggedContext); }
    static constexpr intptr_t kElementSize = kBytesPerElement;
  };

  static intptr_t variable_offset(intptr_t context_index) {
    return OFFSET_OF_RETURNED_VALUE(UntaggedContext, data) +
           (kBytesPerElement * context_index);
  }

  static bool IsValidLength(intptr_t len) {
    return 0 <= len && len <= compiler::target::Context::kMaxElements;
  }

  static intptr_t InstanceSize() {
    ASSERT(sizeof(UntaggedContext) ==
           OFFSET_OF_RETURNED_VALUE(UntaggedContext, data));
    return 0;
  }

  static intptr_t InstanceSize(intptr_t len) {
    ASSERT(IsValidLength(len));
    return RoundedAllocationSize(sizeof(UntaggedContext) +
                                 (len * kBytesPerElement));
  }

  static ContextPtr New(intptr_t num_variables, Heap::Space space = Heap::kNew);

 private:
  void set_num_variables(intptr_t num_variables) const {
    StoreNonPointer(&untag()->num_variables_, num_variables);
  }

  FINAL_HEAP_OBJECT_IMPLEMENTATION(Context, Object);
  friend class Class;
  friend class Object;
};

// The ContextScope class makes it possible to delay the compilation of a local
// function until it is invoked. A ContextScope instance collects the local
// variables that are referenced by the local function to be compiled and that
// belong to the outer scopes, that is, to the local scopes of (possibly nested)
// functions enclosing the local function. Each captured variable is represented
// by its token position in the source, its name, its type, its allocation index
// in the context, and its context level. The function nesting level and loop
// nesting level are not preserved, since they are only used until the context
// level is assigned. In addition the ContextScope has a field 'is_implicit'
// which is true if the ContextScope was created for an implicit closure.
class ContextScope : public Object {
 public:
  intptr_t num_variables() const { return untag()->num_variables_; }

  TokenPosition TokenIndexAt(intptr_t scope_index) const;
  void SetTokenIndexAt(intptr_t scope_index, TokenPosition token_pos) const;

  TokenPosition DeclarationTokenIndexAt(intptr_t scope_index) const;
  void SetDeclarationTokenIndexAt(intptr_t scope_index,
                                  TokenPosition declaration_token_pos) const;

  StringPtr NameAt(intptr_t scope_index) const;
  void SetNameAt(intptr_t scope_index, const String& name) const;

  void ClearFlagsAt(intptr_t scope_index) const;

  bool IsFinalAt(intptr_t scope_index) const;
  void SetIsFinalAt(intptr_t scope_index, bool is_final) const;

  bool IsLateAt(intptr_t scope_index) const;
  void SetIsLateAt(intptr_t scope_index, bool is_late) const;

  intptr_t LateInitOffsetAt(intptr_t scope_index) const;
  void SetLateInitOffsetAt(intptr_t scope_index,
                           intptr_t late_init_offset) const;

  bool IsConstAt(intptr_t scope_index) const;
  void SetIsConstAt(intptr_t scope_index, bool is_const) const;

  AbstractTypePtr TypeAt(intptr_t scope_index) const;
  void SetTypeAt(intptr_t scope_index, const AbstractType& type) const;

  InstancePtr ConstValueAt(intptr_t scope_index) const;
  void SetConstValueAt(intptr_t scope_index, const Instance& value) const;

  intptr_t ContextIndexAt(intptr_t scope_index) const;
  void SetContextIndexAt(intptr_t scope_index, intptr_t context_index) const;

  intptr_t ContextLevelAt(intptr_t scope_index) const;
  void SetContextLevelAt(intptr_t scope_index, intptr_t context_level) const;

  static const intptr_t kBytesPerElement =
      sizeof(UntaggedContextScope::VariableDesc);
  static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;

  struct ArrayTraits {
    static intptr_t elements_start_offset() {
      return sizeof(UntaggedContextScope);
    }
    static constexpr intptr_t kElementSize = kBytesPerElement;
  };

  static intptr_t InstanceSize() {
    ASSERT(sizeof(UntaggedContextScope) ==
           OFFSET_OF_RETURNED_VALUE(UntaggedContextScope, data));
    return 0;
  }

  static intptr_t InstanceSize(intptr_t len) {
    ASSERT(0 <= len && len <= kMaxElements);
    return RoundedAllocationSize(sizeof(UntaggedContextScope) +
                                 (len * kBytesPerElement));
  }

  static ContextScopePtr New(intptr_t num_variables, bool is_implicit);

 private:
  void set_num_variables(intptr_t num_variables) const {
    StoreNonPointer(&untag()->num_variables_, num_variables);
  }

  void set_is_implicit(bool is_implicit) const {
    StoreNonPointer(&untag()->is_implicit_, is_implicit);
  }

  const UntaggedContextScope::VariableDesc* VariableDescAddr(
      intptr_t index) const {
    ASSERT((index >= 0) && (index < num_variables()));
    return untag()->VariableDescAddr(index);
  }

  bool GetFlagAt(intptr_t scope_index, intptr_t mask) const;
  void SetFlagAt(intptr_t scope_index, intptr_t mask, bool value) const;

  FINAL_HEAP_OBJECT_IMPLEMENTATION(ContextScope, Object);
  friend class Class;
  friend class Object;
};

// Class of special sentinel values:
// - Object::sentinel() is a value that cannot be produced by Dart code.
// It can be used to mark special values, for example to distinguish
// "uninitialized" fields.
// - Object::transition_sentinel() is a value marking that we are transitioning
// from sentinel, e.g., computing a field value. Used to detect circular
// initialization of static fields.
// - Object::unknown_constant() and Object::non_constant() are optimizing
// compiler's constant propagation constants.
class Sentinel : public Object {
 public:
  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedSentinel));
  }

  static SentinelPtr New();

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(Sentinel, Object);
  friend class Class;
  friend class Object;
};

class MegamorphicCache : public CallSiteData {
 public:
  static const intptr_t kInitialCapacity = 16;
  static const intptr_t kSpreadFactor = 7;
  static const double kLoadFactor;

  enum EntryType {
    kClassIdIndex,
    kTargetFunctionIndex,
    kEntryLength,
  };

  ArrayPtr buckets() const;
  void set_buckets(const Array& buckets) const;

  intptr_t mask() const;
  void set_mask(intptr_t mask) const;

  intptr_t filled_entry_count() const;
  void set_filled_entry_count(intptr_t num) const;

  static intptr_t buckets_offset() {
    return OFFSET_OF(UntaggedMegamorphicCache, buckets_);
  }
  static intptr_t mask_offset() {
    return OFFSET_OF(UntaggedMegamorphicCache, mask_);
  }
  static intptr_t arguments_descriptor_offset() {
    return OFFSET_OF(UntaggedMegamorphicCache, args_descriptor_);
  }

  static MegamorphicCachePtr New(const String& target_name,
                                 const Array& arguments_descriptor);

  void EnsureContains(const Smi& class_id, const Object& target) const;
  ObjectPtr Lookup(const Smi& class_id) const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedMegamorphicCache));
  }

 private:
  friend class Class;
  friend class MegamorphicCacheTable;
  friend class ProgramVisitor;

  static MegamorphicCachePtr New();

  // The caller must hold IsolateGroup::type_feedback_mutex().
  void InsertLocked(const Smi& class_id, const Object& target) const;
  void EnsureCapacityLocked() const;
  ObjectPtr LookupLocked(const Smi& class_id) const;

  void InsertEntryLocked(const Smi& class_id, const Object& target) const;

  static inline void SetEntry(const Array& array,
                              intptr_t index,
                              const Smi& class_id,
                              const Object& target);

  static inline ObjectPtr GetClassId(const Array& array, intptr_t index);
  static inline ObjectPtr GetTargetFunction(const Array& array, intptr_t index);

  FINAL_HEAP_OBJECT_IMPLEMENTATION(MegamorphicCache, CallSiteData);
};

class SubtypeTestCache : public Object {
 public:
  enum Entries {
    kTestResult = 0,
    kInstanceCidOrSignature = 1,
    kDestinationType = 2,
    kInstanceTypeArguments = 3,
    kInstantiatorTypeArguments = 4,
    kFunctionTypeArguments = 5,
    kInstanceParentFunctionTypeArguments = 6,
    kInstanceDelayedFunctionTypeArguments = 7,
    kTestEntryLength = 8,
  };

  virtual intptr_t NumberOfChecks() const;
  void 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;
  void 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;

  // Like GetCheck(), but does not require the subtype test cache mutex and so
  // may see an outdated view of the cache.
  void 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;

  // Returns whether all the elements of an existing cache entry, excluding
  // the result, match the non-pointer arguments. The pointer arguments are
  // out parameters as follows:
  //
  // If [index] is not nullptr, then it is set to the matching entry's index.
  // If [result] is not nullptr, then it is set to the matching entry's result.
  bool 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;

  // Writes the cache entry at index [index] to the given text buffer.
  //
  // The output is comma separated on a single line if [line_prefix] is nullptr,
  // otherwise line breaks followed by [line_prefix] is used as a separator.
  void WriteEntryToBuffer(Zone* zone,
                          BaseTextBuffer* buffer,
                          intptr_t index,
                          const char* line_prefix = nullptr) const;

  // Like WriteEntryToBuffer(), but does not require the subtype test cache
  // mutex and so may see an outdated view of the cache.
  void WriteCurrentEntryToBuffer(Zone* zone,
                                 BaseTextBuffer* buffer,
                                 intptr_t index,
                                 const char* line_prefix = nullptr) const;
  void Reset() const;

  // Tests that [other] contains the same entries in the same order.
  bool Equals(const SubtypeTestCache& other) const;

  // Creates a separate copy of the current STC contents.
  SubtypeTestCachePtr Copy(Thread* thread) const;

  static SubtypeTestCachePtr New();

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedSubtypeTestCache));
  }

  static intptr_t cache_offset() {
    return OFFSET_OF(UntaggedSubtypeTestCache, cache_);
  }

  static void Init();
  static void Cleanup();

  ArrayPtr cache() const;

 private:
  void set_cache(const Array& value) const;

  // A VM heap allocated preinitialized empty subtype entry array.
  static ArrayPtr cached_array_;

  FINAL_HEAP_OBJECT_IMPLEMENTATION(SubtypeTestCache, Object);
  friend class Class;
  friend class VMSerializationRoots;
  friend class VMDeserializationRoots;
};

class LoadingUnit : public Object {
 public:
  static constexpr intptr_t kIllegalId = 0;
  COMPILE_ASSERT(kIllegalId == WeakTable::kNoValue);
  static constexpr intptr_t kRootId = 1;

  static LoadingUnitPtr New();

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedLoadingUnit));
  }

  LoadingUnitPtr parent() const;
  void set_parent(const LoadingUnit& value) const;

  ArrayPtr base_objects() const;
  void set_base_objects(const Array& value) const;

  intptr_t id() const { return untag()->id_; }
  void set_id(intptr_t id) const { StoreNonPointer(&untag()->id_, id); }

  // True once the VM deserializes this unit's snapshot.
  bool loaded() const { return untag()->loaded_; }
  void set_loaded(bool value) const {
    StoreNonPointer(&untag()->loaded_, value);
  }

  // True once the VM invokes the embedder's deferred load callback until the
  // embedder calls Dart_DeferredLoadComplete[Error].
  bool load_outstanding() const { return untag()->load_outstanding_; }
  void set_load_outstanding(bool value) const {
    StoreNonPointer(&untag()->load_outstanding_, value);
  }

  ObjectPtr IssueLoad() const;
  ObjectPtr CompleteLoad(const String& error_message,
                         bool transient_error) const;

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(LoadingUnit, Object);
  friend class Class;
};

class Error : public Object {
 public:
  virtual const char* ToErrorCString() const;

 private:
  HEAP_OBJECT_IMPLEMENTATION(Error, Object);
};

class ApiError : public Error {
 public:
  StringPtr message() const { return untag()->message(); }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedApiError));
  }

  static ApiErrorPtr New(const String& message, Heap::Space space = Heap::kNew);

  virtual const char* ToErrorCString() const;

 private:
  void set_message(const String& message) const;

  static ApiErrorPtr New();

  FINAL_HEAP_OBJECT_IMPLEMENTATION(ApiError, Error);
  friend class Class;
};

class LanguageError : public Error {
 public:
  Report::Kind kind() const {
    return static_cast<Report::Kind>(untag()->kind_);
  }

  // Build, cache, and return formatted message.
  StringPtr FormatMessage() const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedLanguageError));
  }

  // A null script means no source and a negative token_pos means no position.
  static LanguageErrorPtr NewFormatted(const Error& prev_error,
                                       const Script& script,
                                       TokenPosition token_pos,
                                       bool report_after_token,
                                       Report::Kind kind,
                                       Heap::Space space,
                                       const char* format,
                                       ...) PRINTF_ATTRIBUTE(7, 8);

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

  static LanguageErrorPtr New(const String& formatted_message,
                              Report::Kind kind = Report::kError,
                              Heap::Space space = Heap::kNew);

  virtual const char* ToErrorCString() const;

  TokenPosition token_pos() const { return untag()->token_pos_; }

 private:
  ErrorPtr previous_error() const { return untag()->previous_error(); }
  void set_previous_error(const Error& value) const;

  ScriptPtr script() const { return untag()->script(); }
  void set_script(const Script& value) const;

  void set_token_pos(TokenPosition value) const;

  bool report_after_token() const { return untag()->report_after_token_; }
  void set_report_after_token(bool value);

  void set_kind(uint8_t value) const;

  StringPtr message() const { return untag()->message(); }
  void set_message(const String& value) const;

  StringPtr formatted_message() const { return untag()->formatted_message(); }
  void set_formatted_message(const String& value) const;

  static LanguageErrorPtr New();

  FINAL_HEAP_OBJECT_IMPLEMENTATION(LanguageError, Error);
  friend class Class;
};

class UnhandledException : public Error {
 public:
  InstancePtr exception() const { return untag()->exception(); }
  static intptr_t exception_offset() {
    return OFFSET_OF(UntaggedUnhandledException, exception_);
  }

  InstancePtr stacktrace() const { return untag()->stacktrace(); }
  static intptr_t stacktrace_offset() {
    return OFFSET_OF(UntaggedUnhandledException, stacktrace_);
  }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedUnhandledException));
  }

  static UnhandledExceptionPtr New(const Instance& exception,
                                   const Instance& stacktrace,
                                   Heap::Space space = Heap::kNew);

  virtual const char* ToErrorCString() const;

 private:
  static UnhandledExceptionPtr New(Heap::Space space = Heap::kNew);

  void set_exception(const Instance& exception) const;
  void set_stacktrace(const Instance& stacktrace) const;

  FINAL_HEAP_OBJECT_IMPLEMENTATION(UnhandledException, Error);
  friend class Class;
  friend class ObjectStore;
};

class UnwindError : public Error {
 public:
  bool is_user_initiated() const { return untag()->is_user_initiated_; }
  void set_is_user_initiated(bool value) const;

  StringPtr message() const { return untag()->message(); }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedUnwindError));
  }

  static UnwindErrorPtr New(const String& message,
                            Heap::Space space = Heap::kNew);

  virtual const char* ToErrorCString() const;

 private:
  void set_message(const String& message) const;

  FINAL_HEAP_OBJECT_IMPLEMENTATION(UnwindError, Error);
  friend class Class;
};

// Instance is the base class for all instance objects (aka the Object class
// in Dart source code.
class Instance : public Object {
 public:
  // Equality and identity testing.
  // 1. OperatorEquals: true iff 'this == other' is true in Dart code.
  // 2. IsIdenticalTo: true iff 'identical(this, other)' is true in Dart code.
  // 3. CanonicalizeEquals: used to canonicalize compile-time constants, e.g.,
  //    using bitwise equality of fields and list elements.
  // Subclasses where 1 and 3 coincide may also define a plain Equals, e.g.,
  // String and Integer.
  virtual bool OperatorEquals(const Instance& other) const;
  bool IsIdenticalTo(const Instance& other) const;
  virtual bool CanonicalizeEquals(const Instance& other) const;
  virtual uint32_t CanonicalizeHash() const;

  intptr_t SizeFromClass() const {
#if defined(DEBUG)
    const Class& cls = Class::Handle(clazz());
    ASSERT(cls.is_finalized() || cls.is_prefinalized());
#endif
    return (clazz()->untag()->host_instance_size_in_words_ *
            kCompressedWordSize);
  }

  InstancePtr Canonicalize(Thread* thread) const;
  // Caller must hold IsolateGroup::constant_canonicalization_mutex_.
  virtual InstancePtr CanonicalizeLocked(Thread* thread) const;
  virtual void CanonicalizeFieldsLocked(Thread* thread) const;

  InstancePtr CopyShallowToOldSpace(Thread* thread) const;

#if defined(DEBUG)
  // Check if instance is canonical.
  virtual bool CheckIsCanonical(Thread* thread) const;
#endif  // DEBUG

  ObjectPtr GetField(const Field& field) const;

  void SetField(const Field& field, const Object& value) const;

  AbstractTypePtr GetType(Heap::Space space) const;

  // Access the arguments of the [Type] of this [Instance].
  // Note: for [Type]s instead of [Instance]s with a [Type] attached, use
  // [arguments()] and [set_arguments()]
  virtual TypeArgumentsPtr GetTypeArguments() const;
  virtual void SetTypeArguments(const TypeArguments& value) const;

  // Check if the type of this instance is a subtype of the given other type.
  // The type argument vectors are used to instantiate the other type if needed.
  bool IsInstanceOf(const AbstractType& other,
                    const TypeArguments& other_instantiator_type_arguments,
                    const TypeArguments& other_function_type_arguments) const;

  // Check if this instance is assignable to the given other type.
  // The type argument vectors are used to instantiate the other type if needed.
  bool IsAssignableTo(const AbstractType& other,
                      const TypeArguments& other_instantiator_type_arguments,
                      const TypeArguments& other_function_type_arguments) const;

  // Return true if the null instance can be assigned to a variable of [other]
  // type. Return false if null cannot be assigned or we cannot tell (if
  // [other] is a type parameter in NNBD strong mode). Only used for checks at
  // compile time.
  static bool NullIsAssignableTo(const AbstractType& other);

  // Return true if the null instance can be assigned to a variable of [other]
  // type. Return false if null cannot be assigned. Used for checks at runtime,
  // when the instantiator and function type argument vectors are available.
  static bool NullIsAssignableTo(
      const AbstractType& other,
      const TypeArguments& other_instantiator_type_arguments,
      const TypeArguments& other_function_type_arguments);

  bool IsValidNativeIndex(int index) const {
    return ((index >= 0) && (index < clazz()->untag()->num_native_fields_));
  }

  intptr_t* NativeFieldsDataAddr() const;
  inline intptr_t GetNativeField(int index) const;
  inline void GetNativeFields(uint16_t num_fields,
                              intptr_t* field_values) const;
  void SetNativeFields(uint16_t num_fields, const intptr_t* field_values) const;

  uint16_t NumNativeFields() const {
    return clazz()->untag()->num_native_fields_;
  }

  void SetNativeField(int index, intptr_t value) const;

  // If the instance is a callable object, i.e. a closure or the instance of a
  // class implementing a 'call' method, return true and set the function
  // (if not NULL) to call.
  bool IsCallable(Function* function) const;

  ObjectPtr Invoke(const String& selector,
                   const Array& arguments,
                   const Array& argument_names,
                   bool respect_reflectable = true,
                   bool check_is_entrypoint = false) const;
  ObjectPtr InvokeGetter(const String& selector,
                         bool respect_reflectable = true,
                         bool check_is_entrypoint = false) const;
  ObjectPtr InvokeSetter(const String& selector,
                         const Instance& argument,
                         bool respect_reflectable = true,
                         bool check_is_entrypoint = false) const;

  // Evaluate the given expression as if it appeared in an instance method of
  // this instance and return the resulting value, or an error object if
  // evaluating the expression fails. The method has the formal (type)
  // parameters given in (type_)param_names, and is invoked with the (type)
  // argument values given in (type_)param_values.
  ObjectPtr EvaluateCompiledExpression(
      const Class& method_cls,
      const ExternalTypedData& kernel_buffer,
      const Array& type_definitions,
      const Array& param_values,
      const TypeArguments& type_param_values) const;

  // Equivalent to invoking hashCode on this instance.
  virtual ObjectPtr HashCode() const;

  // Equivalent to invoking identityHashCode with this instance.
  IntegerPtr IdentityHashCode(Thread* thread) const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedInstance));
  }

  static InstancePtr New(const Class& cls, Heap::Space space = Heap::kNew);

  // Array/list element address computations.
  static intptr_t DataOffsetFor(intptr_t cid);
  static intptr_t ElementSizeFor(intptr_t cid);

  // Pointers may be subtyped, but their subtypes may not get extra fields.
  // The subtype runtime representation has exactly the same object layout,
  // only the class_id is different. So, it is safe to use subtype instances in
  // Pointer handles.
  virtual bool IsPointer() const;

  static intptr_t NextFieldOffset() { return sizeof(UntaggedInstance); }

  static intptr_t NativeFieldsOffset() { return sizeof(UntaggedObject); }

 protected:
#ifndef PRODUCT
  virtual void PrintSharedInstanceJSON(JSONObject* jsobj, bool ref) const;
#endif

 private:
  // Return true if the runtimeType of this instance is a subtype of other type.
  bool RuntimeTypeIsSubtypeOf(
      const AbstractType& other,
      const TypeArguments& other_instantiator_type_arguments,
      const TypeArguments& other_function_type_arguments) const;

  // Returns true if the type of this instance is a subtype of FutureOr<T>
  // specified by instantiated type 'other'.
  // Returns false if other type is not a FutureOr.
  bool RuntimeTypeIsSubtypeOfFutureOr(Zone* zone,
                                      const AbstractType& other) const;

  // Return true if the null instance is an instance of other type.
  static bool NullIsInstanceOf(
      const AbstractType& other,
      const TypeArguments& other_instantiator_type_arguments,
      const TypeArguments& other_function_type_arguments);

  CompressedObjectPtr* FieldAddrAtOffset(intptr_t offset) const {
    ASSERT(IsValidFieldOffset(offset));
    return reinterpret_cast<CompressedObjectPtr*>(raw_value() - kHeapObjectTag +
                                                  offset);
  }
  CompressedObjectPtr* FieldAddr(const Field& field) const {
    return FieldAddrAtOffset(field.HostOffset());
  }
  CompressedObjectPtr* NativeFieldsAddr() const {
    return FieldAddrAtOffset(sizeof(UntaggedObject));
  }
  void SetFieldAtOffset(intptr_t offset, const Object& value) const {
    StoreCompressedPointer(FieldAddrAtOffset(offset), value.ptr());
  }
  bool IsValidFieldOffset(intptr_t offset) const;

  // The following raw methods are used for morphing.
  // They are needed due to the extraction of the class in IsValidFieldOffset.
  CompressedObjectPtr* RawFieldAddrAtOffset(intptr_t offset) const {
    return reinterpret_cast<CompressedObjectPtr*>(raw_value() - kHeapObjectTag +
                                                  offset);
  }
  ObjectPtr RawGetFieldAtOffset(intptr_t offset) const {
    return RawFieldAddrAtOffset(offset)->Decompress(untag()->heap_base());
  }
  void RawSetFieldAtOffset(intptr_t offset, const Object& value) const {
    StoreCompressedPointer(RawFieldAddrAtOffset(offset), value.ptr());
  }

  static InstancePtr NewFromCidAndSize(SharedClassTable* shared_class_table,
                                       classid_t cid,
                                       Heap::Space heap = Heap::kNew);

  // TODO(iposva): Determine if this gets in the way of Smi.
  HEAP_OBJECT_IMPLEMENTATION(Instance, Object);
  friend class ByteBuffer;
  friend class Class;
  friend class Closure;
  friend class Pointer;
  friend class DeferredObject;
  friend class RegExp;
  friend class StubCode;
  friend class TypedDataView;
  friend class InstanceSerializationCluster;
  friend class InstanceDeserializationCluster;
  friend class ClassDeserializationCluster;  // vtable
  friend class InstanceMorpher;
  friend class Obfuscator;  // RawGetFieldAtOffset, RawSetFieldAtOffset
};

class LibraryPrefix : public Instance {
 public:
  StringPtr name() const { return untag()->name(); }
  virtual StringPtr DictionaryName() const { return name(); }

  ArrayPtr imports() const { return untag()->imports(); }
  intptr_t num_imports() const { return untag()->num_imports_; }
  LibraryPtr importer() const { return untag()->importer(); }

  LibraryPtr GetLibrary(int index) const;
  void AddImport(const Namespace& import) const;

  bool is_deferred_load() const { return untag()->is_deferred_load_; }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedLibraryPrefix));
  }

  static LibraryPrefixPtr New(const String& name,
                              const Namespace& import,
                              bool deferred_load,
                              const Library& importer);

 private:
  static const int kInitialSize = 2;
  static const int kIncrementSize = 2;

  void set_name(const String& value) const;
  void set_imports(const Array& value) const;
  void set_num_imports(intptr_t value) const;
  void set_importer(const Library& value) const;

  static LibraryPrefixPtr New();

  FINAL_HEAP_OBJECT_IMPLEMENTATION(LibraryPrefix, Instance);
  friend class Class;
};

// TypeParameters represents a list of formal type parameters with their bounds
// and their default values as calculated by CFE.
class TypeParameters : public Object {
 public:
  intptr_t Length() const;

  static intptr_t names_offset() {
    return OFFSET_OF(UntaggedTypeParameters, names_);
  }
  StringPtr NameAt(intptr_t index) const;
  void SetNameAt(intptr_t index, const String& value) const;

  static intptr_t flags_offset() {
    return OFFSET_OF(UntaggedTypeParameters, flags_);
  }

  static intptr_t bounds_offset() {
    return OFFSET_OF(UntaggedTypeParameters, bounds_);
  }
  AbstractTypePtr BoundAt(intptr_t index) const;
  void SetBoundAt(intptr_t index, const AbstractType& value) const;
  bool AllDynamicBounds() const;

  static intptr_t defaults_offset() {
    return OFFSET_OF(UntaggedTypeParameters, defaults_);
  }
  AbstractTypePtr DefaultAt(intptr_t index) const;
  void SetDefaultAt(intptr_t index, const AbstractType& value) const;
  bool AllDynamicDefaults() const;

  // The isGenericCovariantImpl bits are packed into SMIs in the flags array,
  // but omitted if they're 0.
  bool IsGenericCovariantImplAt(intptr_t index) const;
  void SetIsGenericCovariantImplAt(intptr_t index, bool value) const;

  // The number of flags per Smi should be a power of 2 in order to simplify the
  // generated code accessing the flags array.
#if !defined(DART_COMPRESSED_POINTERS)
  static const intptr_t kFlagsPerSmiShift = kBitsPerWordLog2 - 1;
#else
  static const intptr_t kFlagsPerSmiShift = kBitsPerWordLog2 - 2;
#endif
  static const intptr_t kFlagsPerSmi = 1LL << kFlagsPerSmiShift;
  COMPILE_ASSERT(kFlagsPerSmi < kSmiBits);
  static const intptr_t kFlagsPerSmiMask = kFlagsPerSmi - 1;

  void Print(Thread* thread,
             Zone* zone,
             bool are_class_type_parameters,
             intptr_t base,
             NameVisibility name_visibility,
             BaseTextBuffer* printer) const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedTypeParameters));
  }

  static TypeParametersPtr New(Heap::Space space = Heap::kOld);
  static TypeParametersPtr New(intptr_t count, Heap::Space space = Heap::kOld);

 private:
  ArrayPtr names() const { return untag()->names(); }
  void set_names(const Array& value) const;
  ArrayPtr flags() const { return untag()->flags(); }
  void set_flags(const Array& value) const;
  TypeArgumentsPtr bounds() const { return untag()->bounds(); }
  void set_bounds(const TypeArguments& value) const;
  TypeArgumentsPtr defaults() const { return untag()->defaults(); }
  void set_defaults(const TypeArguments& value) const;

  // Allocate and initialize the flags array to zero.
  void AllocateFlags(Heap::Space space) const;
  // Reset the flags array to null if all flags are zero.
  void OptimizeFlags() const;

  FINAL_HEAP_OBJECT_IMPLEMENTATION(TypeParameters, Object);
  friend class Class;
  friend class ClassFinalizer;
  friend class Function;
  friend class FunctionType;
  friend class Object;
  friend class Precompiler;
};

// A TypeArguments is an array of AbstractType.
class TypeArguments : public Instance {
 public:
  // Hash value for a type argument vector consisting solely of dynamic types.
  static const intptr_t kAllDynamicHash = 1;

  // Returns whether this TypeArguments vector can be used in a context that
  // expects a vector of length [count]. Always true for the null vector.
  bool HasCount(intptr_t count) const;
  static intptr_t length_offset() {
    return OFFSET_OF(UntaggedTypeArguments, length_);
  }
  intptr_t Length() const;
  AbstractTypePtr TypeAt(intptr_t index) const;
  AbstractTypePtr TypeAtNullSafe(intptr_t index) const;
  static intptr_t types_offset() {
    return OFFSET_OF_RETURNED_VALUE(UntaggedTypeArguments, types);
  }
  static intptr_t type_at_offset(intptr_t index) {
    return types_offset() + index * kCompressedWordSize;
  }
  void SetTypeAt(intptr_t index, const AbstractType& value) const;

  struct ArrayTraits {
    static intptr_t elements_start_offset() {
      return TypeArguments::types_offset();
    }

    static constexpr intptr_t kElementSize = kCompressedWordSize;
  };

  // The nullability of a type argument vector represents the nullability of its
  // type elements (up to a maximum number of them, i.e. kNullabilityMaxTypes).
  // It is used at runtime in some cases (predetermined by the compiler) to
  // decide whether the instantiator type arguments (ITA) can be shared instead
  // of performing a more costly instantiation of the uninstantiated type
  // arguments (UTA).
  // The vector nullability is stored as a bit vector (in a Smi field), using
  // 2 bits per type:
  //  - the high bit is set if the type is nullable or legacy.
  //  - the low bit is set if the type is nullable.
  // The nullability is 0 if the vector is longer than kNullabilityMaxTypes.
  // The condition evaluated at runtime to decide whether UTA can share ITA is
  //   (UTA.nullability & ITA.nullability) == UTA.nullability
  // Note that this allows for ITA to be longer than UTA (the bit vector must be
  // stored in the same order as the corresponding type vector, i.e. with the
  // least significant 2 bits representing the nullability of the first type).
  static const intptr_t kNullabilityBitsPerType = 2;
  static const intptr_t kNullabilityMaxTypes =
      kSmiBits / kNullabilityBitsPerType;
  static const intptr_t kNonNullableBits = 0;
  static const intptr_t kNullableBits = 3;
  static const intptr_t kLegacyBits = 2;
  intptr_t nullability() const;
  static intptr_t nullability_offset() {
    return OFFSET_OF(UntaggedTypeArguments, nullability_);
  }

  // The name of this type argument vector, e.g. "<T, dynamic, List<T>, Smi>".
  StringPtr Name() const;

  // The name of this type argument vector, e.g. "<T, dynamic, List<T>, int>".
  // Names of internal classes are mapped to their public interfaces.
  StringPtr UserVisibleName() const;

  // Print the internal or public name of a subvector of this type argument
  // vector, e.g. "<T, dynamic, List<T>, int>".
  void PrintSubvectorName(intptr_t from_index,
                          intptr_t len,
                          NameVisibility name_visibility,
                          BaseTextBuffer* printer) const;
  void PrintTo(BaseTextBuffer* printer) const;

  // Check if the subvector of length 'len' starting at 'from_index' of this
  // type argument vector consists solely of DynamicType.
  bool IsRaw(intptr_t from_index, intptr_t len) const {
    return IsDynamicTypes(false, from_index, len);
  }

  // Check if this type argument vector would consist solely of DynamicType if
  // it was instantiated from both a raw (null) instantiator type arguments and
  // a raw (null) function type arguments, i.e. consider each class type
  // parameter and function type parameters as it would be first instantiated
  // from a vector of dynamic types.
  // Consider only a prefix of length 'len'.
  bool IsRawWhenInstantiatedFromRaw(intptr_t len) const {
    return IsDynamicTypes(true, 0, len);
  }

  // Return true if this vector contains a TypeRef.
  bool IsRecursive(TrailPtr trail = nullptr) const;

  // Return true if this vector contains a non-nullable type.
  bool RequireConstCanonicalTypeErasure(Zone* zone,
                                        intptr_t from_index,
                                        intptr_t len,
                                        TrailPtr trail = nullptr) const;

  TypeArgumentsPtr Prepend(Zone* zone,
                           const TypeArguments& other,
                           intptr_t other_length,
                           intptr_t total_length) const;

  // Concatenate [this] and [other] vectors of type parameters.
  TypeArgumentsPtr ConcatenateTypeParameters(Zone* zone,
                                             const TypeArguments& other) const;

  // Check if the vectors are equal (they may be null).
  bool Equals(const TypeArguments& other) const {
    return IsSubvectorEquivalent(other, 0, IsNull() ? 0 : Length(),
                                 TypeEquality::kCanonical);
  }

  bool IsEquivalent(const TypeArguments& other,
                    TypeEquality kind,
                    TrailPtr trail = nullptr) const {
    // Make a null vector a vector of dynamic as long as the other vector.
    return IsSubvectorEquivalent(other, 0, IsNull() ? other.Length() : Length(),
                                 kind, trail);
  }
  bool IsSubvectorEquivalent(const TypeArguments& other,
                             intptr_t from_index,
                             intptr_t len,
                             TypeEquality kind,
                             TrailPtr trail = nullptr) const;

  // Check if the vector is instantiated (it must not be null).
  bool IsInstantiated(Genericity genericity = kAny,
                      intptr_t num_free_fun_type_params = kAllFree,
                      TrailPtr trail = nullptr) const {
    return IsSubvectorInstantiated(0, Length(), genericity,
                                   num_free_fun_type_params, trail);
  }
  bool IsSubvectorInstantiated(intptr_t from_index,
                               intptr_t len,
                               Genericity genericity = kAny,
                               intptr_t num_free_fun_type_params = kAllFree,
                               TrailPtr trail = nullptr) const;
  bool IsUninstantiatedIdentity() const;

  // Determine whether this uninstantiated type argument vector can share its
  // instantiator (resp. function) type argument vector instead of being
  // instantiated at runtime.
  // If null is passed in for 'with_runtime_check', the answer is unconditional
  // (i.e. the answer will be false even if a runtime check may allow sharing),
  // otherwise, in case the function returns true, 'with_runtime_check'
  // indicates if a check is still required at runtime before allowing sharing.
  bool CanShareInstantiatorTypeArguments(
      const Class& instantiator_class,
      bool* with_runtime_check = nullptr) const;
  bool CanShareFunctionTypeArguments(const Function& function,
                                     bool* with_runtime_check = nullptr) const;

  // Return true if all types of this vector are finalized.
  bool IsFinalized() const;

  // Caller must hold IsolateGroup::constant_canonicalization_mutex_.
  virtual InstancePtr CanonicalizeLocked(Thread* thread) const {
    return Canonicalize(thread, nullptr);
  }

  // Canonicalize only if instantiated, otherwise returns 'this'.
  TypeArgumentsPtr Canonicalize(Thread* thread, TrailPtr trail = nullptr) const;

  // Add the class name and URI of each type argument of this vector to the uris
  // list and mark ambiguous triplets to be printed.
  void EnumerateURIs(URIs* uris) const;

  // Return 'this' if this type argument vector is instantiated, i.e. if it does
  // not refer to type parameters. Otherwise, return a new type argument vector
  // where each reference to a type parameter is replaced with the corresponding
  // type from the various type argument vectors (class instantiator, function,
  // or parent functions via the current context).
  TypeArgumentsPtr InstantiateFrom(
      const TypeArguments& instantiator_type_arguments,
      const TypeArguments& function_type_arguments,
      intptr_t num_free_fun_type_params,
      Heap::Space space,
      TrailPtr trail = nullptr) const;

  // Runtime instantiation with canonicalization. Not to be used during type
  // finalization at compile time.
  TypeArgumentsPtr InstantiateAndCanonicalizeFrom(
      const TypeArguments& instantiator_type_arguments,
      const TypeArguments& function_type_arguments) const;

  // Each cached instantiation consists of a 3-tuple in the instantiations_
  // array stored in each canonical uninstantiated type argument vector.
  enum Instantiation {
    kInstantiatorTypeArgsIndex = 0,
    kFunctionTypeArgsIndex,
    kInstantiatedTypeArgsIndex,
    kSizeInWords,
  };

  // The array is terminated by the value kNoInstantiator occuring in place of
  // the instantiator type args of the 4-tuple that would otherwise follow.
  // Therefore, kNoInstantiator must be distinct from any type arguments vector,
  // even a null one. Since arrays are initialized with 0, the instantiations_
  // array is properly terminated upon initialization.
  static const intptr_t kNoInstantiator = 0;

  // Return true if this type argument vector has cached instantiations.
  bool HasInstantiations() const;

  // Return the number of cached instantiations for this type argument vector.
  intptr_t NumInstantiations() const;

  static intptr_t instantiations_offset() {
    return OFFSET_OF(UntaggedTypeArguments, instantiations_);
  }

  static const intptr_t kBytesPerElement = kCompressedWordSize;
  static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;

  static intptr_t InstanceSize() {
    ASSERT(sizeof(UntaggedTypeArguments) ==
           OFFSET_OF_RETURNED_VALUE(UntaggedTypeArguments, types));
    return 0;
  }

  static intptr_t InstanceSize(intptr_t len) {
    // Ensure that the types() is not adding to the object size, which includes
    // 4 fields: instantiations_, length_, hash_, and nullability_.
    ASSERT(sizeof(UntaggedTypeArguments) ==
           (sizeof(UntaggedObject) + (kNumFields * kCompressedWordSize)));
    ASSERT(0 <= len && len <= kMaxElements);
    return RoundedAllocationSize(sizeof(UntaggedTypeArguments) +
                                 (len * kBytesPerElement));
  }

  virtual uint32_t CanonicalizeHash() const {
    // Hash() is not stable until finalization is done.
    return 0;
  }
  uword Hash() const;
  uword HashForRange(intptr_t from_index, intptr_t len) const;

  static TypeArgumentsPtr New(intptr_t len, Heap::Space space = Heap::kOld);

 private:
  intptr_t ComputeNullability() const;
  void set_nullability(intptr_t value) const;

  uword ComputeHash() const;
  void SetHash(intptr_t value) const;

  // Check if the subvector of length 'len' starting at 'from_index' of this
  // type argument vector consists solely of DynamicType.
  // If raw_instantiated is true, consider each class type parameter to be first
  // instantiated from a vector of dynamic types.
  bool IsDynamicTypes(bool raw_instantiated,
                      intptr_t from_index,
                      intptr_t len) const;

  ArrayPtr instantiations() const;
  void set_instantiations(const Array& value) const;
  void SetLength(intptr_t value) const;
  // Number of fields in the raw object is 4:
  // instantiations_, length_, hash_ and nullability_.
  static const int kNumFields = 4;

  FINAL_HEAP_OBJECT_IMPLEMENTATION(TypeArguments, Instance);
  friend class AbstractType;
  friend class Class;
  friend class ClearTypeHashVisitor;
  friend class Object;
};

// AbstractType is an abstract superclass.
// Subclasses of AbstractType are Type and TypeParameter.
class AbstractType : public Instance {
 public:
  virtual bool IsFinalized() const;
  virtual void SetIsFinalized() const;
  virtual bool IsBeingFinalized() const;
  virtual void SetIsBeingFinalized() const;

  virtual Nullability nullability() const;
  // Returns true if type has '?' nullability suffix, or it is a
  // built-in type which is always nullable (Null, dynamic or void).
  bool IsNullable() const { return nullability() == Nullability::kNullable; }
  // Returns true if type does not have any nullability suffix.
  // This function also returns true for type parameters without
  // nullability suffix ("T") which can be instantiated with
  // nullable or legacy types.
  bool IsNonNullable() const {
    return nullability() == Nullability::kNonNullable;
  }
  // Returns true if type has '*' nullability suffix, i.e.
  // it is from a legacy (opted-out) library.
  bool IsLegacy() const { return nullability() == Nullability::kLegacy; }
  // Returns true if it is guaranteed that null cannot be
  // assigned to this type.
  bool IsStrictlyNonNullable() const;

  virtual AbstractTypePtr SetInstantiatedNullability(
      const TypeParameter& type_param,
      Heap::Space space) const;
  virtual AbstractTypePtr NormalizeFutureOrType(Heap::Space space) const;

  virtual bool HasTypeClass() const { return type_class_id() != kIllegalCid; }
  virtual classid_t type_class_id() const;
  virtual ClassPtr type_class() const;
  virtual TypeArgumentsPtr arguments() const;
  virtual void set_arguments(const TypeArguments& value) const;
  virtual bool IsInstantiated(Genericity genericity = kAny,
                              intptr_t num_free_fun_type_params = kAllFree,
                              TrailPtr trail = nullptr) const;
  virtual bool CanonicalizeEquals(const Instance& other) const {
    return Equals(other);
  }
  virtual uint32_t CanonicalizeHash() const { return Hash(); }
  virtual bool Equals(const Instance& other) const {
    return IsEquivalent(other, TypeEquality::kCanonical);
  }
  virtual bool IsEquivalent(const Instance& other,
                            TypeEquality kind,
                            TrailPtr trail = nullptr) const;
  virtual bool IsRecursive(TrailPtr trail = nullptr) const;
  virtual bool RequireConstCanonicalTypeErasure(Zone* zone,
                                                TrailPtr trail = nullptr) const;

  // Instantiate this type using the given type argument vectors.
  //
  // Note that some type parameters appearing in this type may not require
  // instantiation. Consider a class C<T> declaring a non-generic method
  // foo(bar<B>(T t, B b)). Although foo is not a generic method, it takes a
  // generic function bar<B> as argument and its function type refers to class
  // type parameter T and function type parameter B. When instantiating the
  // function type of foo for a particular value of T, function type parameter B
  // must remain uninstantiated, because only T is a free variable in this type.
  //
  // Return a new type, or return 'this' if it is already instantiated.
  virtual AbstractTypePtr InstantiateFrom(
      const TypeArguments& instantiator_type_arguments,
      const TypeArguments& function_type_arguments,
      intptr_t num_free_fun_type_params,
      Heap::Space space,
      TrailPtr trail = nullptr) const;

  // Caller must hold IsolateGroup::constant_canonicalization_mutex_.
  virtual InstancePtr CanonicalizeLocked(Thread* thread) const {
    return Canonicalize(thread, nullptr);
  }

  // Return the canonical version of this type.
  virtual AbstractTypePtr Canonicalize(Thread* thread, TrailPtr trail) const;

#if defined(DEBUG)
  // Check if abstract type is canonical.
  virtual bool CheckIsCanonical(Thread* thread) const {
    UNREACHABLE();
    return false;
  }
#endif  // DEBUG

  // Return the object associated with the receiver in the trail or
  // AbstractType::null() if the receiver is not contained in the trail.
  AbstractTypePtr OnlyBuddyInTrail(TrailPtr trail) const;

  // If the trail is null, allocate a trail, add the pair <receiver, buddy> to
  // the trail. The receiver may only be added once with its only buddy.
  void AddOnlyBuddyToTrail(TrailPtr* trail, const AbstractType& buddy) const;

  // Return true if the receiver is contained in the trail.
  // Otherwise, if the trail is null, allocate a trail, then add the receiver to
  // the trail and return false.
  bool TestAndAddToTrail(TrailPtr* trail) const;

  // Return true if the pair <receiver, buddy> is contained in the trail.
  // Otherwise, if the trail is null, allocate a trail, add the pair <receiver,
  // buddy> to the trail and return false.
  // The receiver may be added several times, each time with a different buddy.
  bool TestAndAddBuddyToTrail(TrailPtr* trail, const AbstractType& buddy) const;

  // Add the pair <name, uri> to the list, if not already present.
  static void AddURI(URIs* uris, const String& name, const String& uri);

  // Return a formatted string of the uris.
  static StringPtr PrintURIs(URIs* uris);

  // Returns a C-String (possibly "") representing the nullability of this type.
  // Legacy and undetermined suffixes are only displayed with kInternalName.
  virtual const char* NullabilitySuffix(NameVisibility name_visibility) const;

  // The name of this type, including the names of its type arguments, if any.
  virtual StringPtr Name() const;

  // The name of this type, including the names of its type arguments, if any.
  // Names of internal classes are mapped to their public interfaces.
  virtual StringPtr UserVisibleName() const;

  // The name of this type, including the names of its type arguments, if any.
  // Privacy suffixes are dropped.
  virtual StringPtr ScrubbedName() const;

  // Return the internal or public name of this type, including the names of its
  // type arguments, if any.
  void PrintName(NameVisibility visibility, BaseTextBuffer* printer) const;

  // Add the class name and URI of each occuring type to the uris
  // list and mark ambiguous triplets to be printed.
  virtual void EnumerateURIs(URIs* uris) const;

  virtual uword Hash() const;

  // The name of this type's class, i.e. without the type argument names of this
  // type.
  StringPtr ClassName() const;

  // Check if this type is a still uninitialized TypeRef.
  bool IsNullTypeRef() const;

  // Check if this type represents the 'dynamic' type.
  bool IsDynamicType() const { return type_class_id() == kDynamicCid; }

  // Check if this type represents the 'void' type.
  bool IsVoidType() const { return type_class_id() == kVoidCid; }

  // Check if this type represents the 'Null' type.
  bool IsNullType() const;

  // Check if this type represents the 'Never' type.
  bool IsNeverType() const;

  // Check if this type represents the 'Sentinel' type.
  bool IsSentinelType() const;

  // Check if this type represents the 'Object' type.
  bool IsObjectType() const { return type_class_id() == kInstanceCid; }

  // Check if this type represents a top type for subtyping,
  // assignability and 'as' type tests.
  //
  // Returns true if
  //  - any type is a subtype of this type;
  //  - any value can be assigned to a variable of this type;
  //  - 'as' type test always succeeds for this type.
  bool IsTopTypeForSubtyping() const;

  // Check if this type represents a top type for 'is' type tests.
  // Returns true if 'is' type test always returns true for this type.
  bool IsTopTypeForInstanceOf() const;

  // Check if this type represents the 'bool' type.
  bool IsBoolType() const { return type_class_id() == kBoolCid; }

  // Check if this type represents the 'int' type.
  bool IsIntType() const;

  // Check if this type represents the '_IntegerImplementation' type.
  bool IsIntegerImplementationType() const;

  // Check if this type represents the 'double' type.
  bool IsDoubleType() const;

  // Check if this type represents the 'Float32x4' type.
  bool IsFloat32x4Type() const;

  // Check if this type represents the 'Float64x2' type.
  bool IsFloat64x2Type() const;

  // Check if this type represents the 'Int32x4' type.
  bool IsInt32x4Type() const;

  // Check if this type represents the 'num' type.
  bool IsNumberType() const { return type_class_id() == kNumberCid; }

  // Check if this type represents the '_Smi' type.
  bool IsSmiType() const { return type_class_id() == kSmiCid; }

  // Check if this type represents the '_Mint' type.
  bool IsMintType() const { return type_class_id() == kMintCid; }

  // Check if this type represents the 'String' type.
  bool IsStringType() const;

  // Check if this type represents the Dart 'Function' type.
  bool IsDartFunctionType() const;

  // Check if this type represents the Dart '_Closure' type.
  bool IsDartClosureType() const;

  // Check if this type represents the 'Pointer' type from "dart:ffi".
  bool IsFfiPointerType() const;

  // Check if this type represents the 'FutureOr' type.
  bool IsFutureOrType() const { return type_class_id() == kFutureOrCid; }

  // Returns the type argument of this (possibly nested) 'FutureOr' type.
  // Returns unmodified type if this type is not a 'FutureOr' type.
  AbstractTypePtr UnwrapFutureOr() const;

  // Returns true if catching this type will catch all exceptions.
  // Exception objects are guaranteed to be non-nullable, so
  // non-nullable Object is also a catch-all type.
  bool IsCatchAllType() const { return IsDynamicType() || IsObjectType(); }

  // Check the subtype relationship.
  bool IsSubtypeOf(const AbstractType& other,
                   Heap::Space space,
                   TrailPtr trail = nullptr) const;

  // Returns true iff subtype is a subtype of supertype, false otherwise or if
  // an error occurred.
  static bool InstantiateAndTestSubtype(
      AbstractType* subtype,
      AbstractType* supertype,
      const TypeArguments& instantiator_type_args,
      const TypeArguments& function_type_args);

  static intptr_t type_test_stub_entry_point_offset() {
    return OFFSET_OF(UntaggedAbstractType, type_test_stub_entry_point_);
  }

  uword type_test_stub_entry_point() const {
    return untag()->type_test_stub_entry_point_;
  }
  CodePtr type_test_stub() const { return untag()->type_test_stub(); }

  // Sets the TTS to [stub].
  //
  // The update will ensure both fields (code as well as the cached entrypoint)
  // are updated together.
  //
  // Can be used concurrently by multiple threads - the updates will be applied
  // in undetermined order - but always consistently.
  void SetTypeTestingStub(const Code& stub) const;

  // Sets the TTS to the [stub].
  //
  // The caller has to ensure no other thread can concurrently try to update the
  // TTS. This should mainly be used when initializing newly allocated Type
  // objects.
  void InitializeTypeTestingStubNonAtomic(const Code& stub) const;

  void UpdateTypeTestingStubEntryPoint() const {
    StoreNonPointer(&untag()->type_test_stub_entry_point_,
                    Code::EntryPointOf(untag()->type_test_stub()));
  }

  // No instances of type AbstractType are allocated, but InstanceSize() and
  // NextFieldOffset() are required to register class _AbstractType.
  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedAbstractType));
  }

  static intptr_t NextFieldOffset() { return -kWordSize; }

 private:
  // Returns true if this type is a subtype of FutureOr<T> specified by 'other'.
  // Returns false if other type is not a FutureOr.
  bool IsSubtypeOfFutureOr(Zone* zone,
                           const AbstractType& other,
                           Heap::Space space,
                           TrailPtr trail = nullptr) const;

 protected:
  HEAP_OBJECT_IMPLEMENTATION(AbstractType, Instance);
  friend class Class;
  friend class Function;
  friend class TypeArguments;
};

// A Type consists of a class, possibly parameterized with type
// arguments. Example: C<T1, T2>.
class Type : public AbstractType {
 public:
  static intptr_t type_class_id_offset() {
    return OFFSET_OF(UntaggedType, type_class_id_);
  }
  static intptr_t arguments_offset() {
    return OFFSET_OF(UntaggedType, arguments_);
  }
  static intptr_t type_state_offset() {
    return OFFSET_OF(UntaggedType, type_state_);
  }
  static intptr_t hash_offset() { return OFFSET_OF(UntaggedType, hash_); }
  static intptr_t nullability_offset() {
    return OFFSET_OF(UntaggedType, nullability_);
  }
  virtual bool IsFinalized() const {
    return (untag()->type_state_ == UntaggedType::kFinalizedInstantiated) ||
           (untag()->type_state_ == UntaggedType::kFinalizedUninstantiated);
  }
  virtual void SetIsFinalized() const;
  virtual bool IsBeingFinalized() const {
    return untag()->type_state_ == UntaggedType::kBeingFinalized;
  }
  virtual void SetIsBeingFinalized() const;
  virtual bool HasTypeClass() const {
    ASSERT(type_class_id() != kIllegalCid);
    return true;
  }
  virtual Nullability nullability() const {
    return static_cast<Nullability>(untag()->nullability_);
  }
  TypePtr ToNullability(Nullability value, Heap::Space space) const;
  virtual classid_t type_class_id() const;
  virtual ClassPtr type_class() const;
  void set_type_class(const Class& value) const;
  virtual TypeArgumentsPtr arguments() const { return untag()->arguments(); }
  virtual void set_arguments(const TypeArguments& value) const;
  virtual bool IsInstantiated(Genericity genericity = kAny,
                              intptr_t num_free_fun_type_params = kAllFree,
                              TrailPtr trail = nullptr) const;
  virtual bool IsEquivalent(const Instance& other,
                            TypeEquality kind,
                            TrailPtr trail = nullptr) const;
  virtual bool IsRecursive(TrailPtr trail = nullptr) const;
  virtual bool RequireConstCanonicalTypeErasure(Zone* zone,
                                                TrailPtr trail = nullptr) const;

  // Return true if this type can be used as the declaration type of cls after
  // canonicalization (passed-in cls must match type_class()).
  bool IsDeclarationTypeOf(const Class& cls) const;

  virtual AbstractTypePtr InstantiateFrom(
      const TypeArguments& instantiator_type_arguments,
      const TypeArguments& function_type_arguments,
      intptr_t num_free_fun_type_params,
      Heap::Space space,
      TrailPtr trail = nullptr) const;
  virtual AbstractTypePtr Canonicalize(Thread* thread, TrailPtr trail) const;
#if defined(DEBUG)
  // Check if type is canonical.
  virtual bool CheckIsCanonical(Thread* thread) const;
#endif  // DEBUG
  virtual void EnumerateURIs(URIs* uris) const;

  virtual uword Hash() const;
  uword ComputeHash() const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedType));
  }

  // The type of the literal 'null'.
  static TypePtr NullType();

  // The 'dynamic' type.
  static TypePtr DynamicType();

  // The 'void' type.
  static TypePtr VoidType();

  // The 'Never' type.
  static TypePtr NeverType();

  // The 'Object' type.
  static TypePtr ObjectType();

  // The 'bool' type.
  static TypePtr BoolType();

  // The 'int' type.
  static TypePtr IntType();

  // The 'int?' type.
  static TypePtr NullableIntType();

  // The 'Smi' type.
  static TypePtr SmiType();

  // The 'Mint' type.
  static TypePtr MintType();

  // The 'double' type.
  static TypePtr Double();

  // The 'double?' type.
  static TypePtr NullableDouble();

  // The 'Float32x4' type.
  static TypePtr Float32x4();

  // The 'Float64x2' type.
  static TypePtr Float64x2();

  // The 'Int32x4' type.
  static TypePtr Int32x4();

  // The 'num' type.
  static TypePtr Number();

  // The 'String' type.
  static TypePtr StringType();

  // The 'Array' type.
  static TypePtr ArrayType();

  // The 'Function' type.
  static TypePtr DartFunctionType();

  // The 'Type' type.
  static TypePtr DartTypeType();

  // The finalized type of the given non-parameterized class.
  static TypePtr NewNonParameterizedType(const Class& type_class);

  static TypePtr New(const Class& clazz,
                     const TypeArguments& arguments,
                     Nullability nullability = Nullability::kLegacy,
                     Heap::Space space = Heap::kOld);

 private:
  void SetHash(intptr_t value) const;

  // Takes an intptr_t since the cids of some classes are larger than will fit
  // in ClassIdTagType. This allows us to guard against that case, instead of
  // silently truncating the cid.
  void set_type_class_id(intptr_t id) const;
  void set_type_state(uint8_t state) const;
  void set_nullability(Nullability value) const {
    ASSERT(!IsCanonical());
    StoreNonPointer(&untag()->nullability_, static_cast<uint8_t>(value));
  }

  static TypePtr New(Heap::Space space = Heap::kOld);

  FINAL_HEAP_OBJECT_IMPLEMENTATION(Type, AbstractType);
  friend class Class;
  friend class TypeArguments;
  friend class ClearTypeHashVisitor;
};

// A FunctionType represents the type of a function. It describes most of the
// signature of a function, excluding the names of type parameters and names
// of parameters, but includes the names of optional named parameters.
class FunctionType : public AbstractType {
 public:
  // Reexported so they can be used by the flow graph builders.
  using PackedNumParentTypeArguments =
      UntaggedFunctionType::PackedNumParentTypeArguments;
  using PackedNumTypeParameters = UntaggedFunctionType::PackedNumTypeParameters;
  using PackedHasNamedOptionalParameters =
      UntaggedFunctionType::PackedHasNamedOptionalParameters;
  using PackedNumImplicitParameters =
      UntaggedFunctionType::PackedNumImplicitParameters;
  using PackedNumFixedParameters =
      UntaggedFunctionType::PackedNumFixedParameters;
  using PackedNumOptionalParameters =
      UntaggedFunctionType::PackedNumOptionalParameters;

  static intptr_t type_state_offset() {
    return OFFSET_OF(UntaggedFunctionType, type_state_);
  }
  static intptr_t hash_offset() {
    return OFFSET_OF(UntaggedFunctionType, hash_);
  }
  static intptr_t nullability_offset() {
    return OFFSET_OF(UntaggedFunctionType, nullability_);
  }
  virtual bool IsFinalized() const {
    return (untag()->type_state_ == UntaggedType::kFinalizedInstantiated) ||
           (untag()->type_state_ == UntaggedType::kFinalizedUninstantiated);
  }
  virtual void SetIsFinalized() const;
  virtual bool IsBeingFinalized() const {
    return untag()->type_state_ == UntaggedType::kBeingFinalized;
  }
  virtual void SetIsBeingFinalized() const;
  virtual bool HasTypeClass() const { return false; }
  virtual Nullability nullability() const {
    return static_cast<Nullability>(untag()->nullability_);
  }
  FunctionTypePtr ToNullability(Nullability value, Heap::Space space) const;
  virtual classid_t type_class_id() const { return kIllegalCid; }
  virtual bool IsInstantiated(Genericity genericity = kAny,
                              intptr_t num_free_fun_type_params = kAllFree,
                              TrailPtr trail = nullptr) const;
  virtual bool IsEquivalent(const Instance& other,
                            TypeEquality kind,
                            TrailPtr trail = nullptr) const;
  virtual bool IsRecursive(TrailPtr trail = nullptr) const;
  virtual bool RequireConstCanonicalTypeErasure(Zone* zone,
                                                TrailPtr trail = nullptr) const;

  virtual AbstractTypePtr InstantiateFrom(
      const TypeArguments& instantiator_type_arguments,
      const TypeArguments& function_type_arguments,
      intptr_t num_free_fun_type_params,
      Heap::Space space,
      TrailPtr trail = nullptr) const;
  virtual AbstractTypePtr Canonicalize(Thread* thread, TrailPtr trail) const;
#if defined(DEBUG)
  // Check if type is canonical.
  virtual bool CheckIsCanonical(Thread* thread) const;
#endif  // DEBUG
  virtual void EnumerateURIs(URIs* uris) const;

  virtual uword Hash() const;
  uword ComputeHash() const;

  bool IsSubtypeOf(const FunctionType& other, Heap::Space space) const;

  static intptr_t NumParentTypeArgumentsOf(FunctionTypePtr ptr) {
    return ptr->untag()
        ->packed_type_parameter_counts_.Read<PackedNumParentTypeArguments>();
  }
  // Return the number of type arguments in the enclosing signature.
  intptr_t NumParentTypeArguments() const {
    return NumParentTypeArgumentsOf(ptr());
  }
  void SetNumParentTypeArguments(intptr_t value) const;
  static intptr_t NumTypeParametersOf(FunctionTypePtr ptr) {
    return ptr->untag()
        ->packed_type_parameter_counts_.Read<PackedNumTypeParameters>();
  }
  intptr_t NumTypeParameters() const { return NumTypeParametersOf(ptr()); }

  static intptr_t NumTypeArgumentsOf(FunctionTypePtr ptr) {
    return NumTypeParametersOf(ptr) + NumParentTypeArgumentsOf(ptr);
  }
  intptr_t NumTypeArguments() const { return NumTypeArgumentsOf(ptr()); }

  intptr_t num_implicit_parameters() const {
    return untag()
        ->packed_parameter_counts_.Read<PackedNumImplicitParameters>();
  }
  void set_num_implicit_parameters(intptr_t value) const;

  static intptr_t NumFixedParametersOf(FunctionTypePtr ptr) {
    return ptr->untag()
        ->packed_parameter_counts_.Read<PackedNumFixedParameters>();
  }
  intptr_t num_fixed_parameters() const { return NumFixedParametersOf(ptr()); }
  void set_num_fixed_parameters(intptr_t value) const;

  static bool HasOptionalParameters(FunctionTypePtr ptr) {
    return ptr->untag()
               ->packed_parameter_counts_.Read<PackedNumOptionalParameters>() >
           0;
  }
  bool HasOptionalParameters() const { return HasOptionalParameters(ptr()); }

  static bool HasOptionalNamedParameters(FunctionTypePtr ptr) {
    return ptr->untag()
        ->packed_parameter_counts_.Read<PackedHasNamedOptionalParameters>();
  }
  bool HasOptionalNamedParameters() const {
    return HasOptionalNamedParameters(ptr());
  }
  bool HasRequiredNamedParameters() const;

  static bool HasOptionalPositionalParameters(FunctionTypePtr ptr) {
    return !HasOptionalNamedParameters(ptr) && HasOptionalParameters(ptr);
  }
  bool HasOptionalPositionalParameters() const {
    return HasOptionalPositionalParameters(ptr());
  }

  static intptr_t NumOptionalParametersOf(FunctionTypePtr ptr) {
    return ptr->untag()
        ->packed_parameter_counts_.Read<PackedNumOptionalParameters>();
  }
  intptr_t NumOptionalParameters() const {
    return NumOptionalParametersOf(ptr());
  }
  void SetNumOptionalParameters(intptr_t num_optional_parameters,
                                bool are_optional_positional) const;

  static intptr_t NumOptionalPositionalParametersOf(FunctionTypePtr ptr) {
    return HasOptionalNamedParameters(ptr) ? 0 : NumOptionalParametersOf(ptr);
  }
  intptr_t NumOptionalPositionalParameters() const {
    return NumOptionalPositionalParametersOf(ptr());
  }

  static intptr_t NumOptionalNamedParametersOf(FunctionTypePtr ptr) {
    return HasOptionalNamedParameters(ptr) ? NumOptionalParametersOf(ptr) : 0;
  }
  intptr_t NumOptionalNamedParameters() const {
    return NumOptionalNamedParametersOf(ptr());
  }

  static intptr_t NumParametersOf(FunctionTypePtr ptr) {
    return NumFixedParametersOf(ptr) + NumOptionalParametersOf(ptr);
  }
  intptr_t NumParameters() const { return NumParametersOf(ptr()); }

  uint32_t packed_parameter_counts() const {
    return untag()->packed_parameter_counts_;
  }
  void set_packed_parameter_counts(uint32_t packed_parameter_counts) const;
  static intptr_t packed_parameter_counts_offset() {
    return OFFSET_OF(UntaggedFunctionType, packed_parameter_counts_);
  }
  uint16_t packed_type_parameter_counts() const {
    return untag()->packed_type_parameter_counts_;
  }
  void set_packed_type_parameter_counts(uint16_t packed_parameter_counts) const;
  static intptr_t packed_type_parameter_counts_offset() {
    return OFFSET_OF(UntaggedFunctionType, packed_type_parameter_counts_);
  }

  // Return the type parameter declared at index.
  TypeParameterPtr TypeParameterAt(
      intptr_t index,
      Nullability nullability = Nullability::kNonNullable) const;

  AbstractTypePtr result_type() const { return untag()->result_type(); }
  void set_result_type(const AbstractType& value) const;

  // The parameters, starting with NumImplicitParameters() parameters which are
  // only visible to the VM, but not to Dart users.
  // Note that type checks exclude implicit parameters.
  AbstractTypePtr ParameterTypeAt(intptr_t index) const;
  void SetParameterTypeAt(intptr_t index, const AbstractType& value) const;
  ArrayPtr parameter_types() const { return untag()->parameter_types(); }
  void set_parameter_types(const Array& value) const;
  static intptr_t parameter_types_offset() {
    return OFFSET_OF(UntaggedFunctionType, parameter_types_);
  }
  // Parameter names are only stored for named parameters. If there are no named
  // parameters, named_parameter_names() is null.
  // If there are parameter flags (eg required) they're stored at the end of
  // this array, so the size of this array isn't necessarily
  // NumOptionalNamedParameters(), but the first NumOptionalNamedParameters()
  // elements are the names.
  ArrayPtr named_parameter_names() const {
    return untag()->named_parameter_names();
  }
  void set_named_parameter_names(const Array& value) const;
  static intptr_t named_parameter_names_offset() {
    return OFFSET_OF(UntaggedFunctionType, named_parameter_names_);
  }
  // The index for these operations is the absolute index of the parameter, not
  // the index relative to the start of the named parameters (if any).
  StringPtr ParameterNameAt(intptr_t index) const;
  // Only valid for absolute indexes of named parameters.
  void SetParameterNameAt(intptr_t index, const String& value) const;

  // The required flags are stored at the end of the parameter_names. The flags
  // are packed into SMIs, but omitted if they're 0.
  bool IsRequiredAt(intptr_t index) const;
  void SetIsRequiredAt(intptr_t index) const;

  // Sets up the signature's parameter name array, including appropriate space
  // for any possible parameter flags. This may be an overestimate if some
  // parameters don't have flags, and so FinalizeNameArray() should
  // be called after all parameter flags have been appropriately set.
  //
  // Assumes that the number of fixed and optional parameters for the signature
  // has already been set. Uses same default space as FunctionType::New.
  void CreateNameArrayIncludingFlags(Heap::Space space = Heap::kOld) const;

  // Truncate the parameter names array to remove any unused flag slots. Make
  // sure to only do this after calling SetIsRequiredAt as necessary.
  void FinalizeNameArray() const;

  // Returns the length of the parameter names array that is required to store
  // all the names plus all their flags. This may be an overestimate if some
  // parameters don't have flags.
  static intptr_t NameArrayLengthIncludingFlags(intptr_t num_parameters);

  // The formal type parameters, their bounds, and defaults, are specified as an
  // object of type TypeParameters.
  TypeParametersPtr type_parameters() const {
    return untag()->type_parameters();
  }
  void SetTypeParameters(const TypeParameters& value) const;
  static intptr_t type_parameters_offset() {
    return OFFSET_OF(UntaggedFunctionType, type_parameters_);
  }

  // Returns true if this function type has the same number of type parameters
  // with equal bounds as the other function type. Type parameter names and
  // parameter names (unless optional named) are ignored.
  bool HasSameTypeParametersAndBounds(const FunctionType& other,
                                      TypeEquality kind,
                                      TrailPtr trail = nullptr) const;

  // Return true if this function type declares type parameters.
  static bool IsGeneric(FunctionTypePtr ptr) {
    return ptr->untag()->type_parameters() != TypeParameters::null();
  }
  bool IsGeneric() const { return IsGeneric(ptr()); }

  // Return true if any enclosing signature of this signature is generic.
  bool HasGenericParent() const { return NumParentTypeArguments() > 0; }

  // Returns true if the type of the formal parameter at the given position in
  // this function type is contravariant with the type of the other formal
  // parameter at the given position in the other function type.
  bool IsContravariantParameter(intptr_t parameter_position,
                                const FunctionType& other,
                                intptr_t other_parameter_position,
                                Heap::Space space) const;

  // Returns the index in the parameter names array of the corresponding flag
  // for the given parametere index. Also returns (via flag_mask) the
  // corresponding mask within the flag.
  intptr_t GetRequiredFlagIndex(intptr_t index, intptr_t* flag_mask) const;

  void Print(NameVisibility name_visibility, BaseTextBuffer* printer) const;
  void PrintParameters(Thread* thread,
                       Zone* zone,
                       NameVisibility name_visibility,
                       BaseTextBuffer* printer) const;

  StringPtr ToUserVisibleString() const;
  const char* ToUserVisibleCString() const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedFunctionType));
  }

  static FunctionTypePtr New(intptr_t num_parent_type_arguments = 0,
                             Nullability nullability = Nullability::kLegacy,
                             Heap::Space space = Heap::kOld);

 private:
  void SetHash(intptr_t value) const;

  void set_type_state(uint8_t state) const;
  void set_nullability(Nullability value) const {
    ASSERT(!IsCanonical());
    StoreNonPointer(&untag()->nullability_, static_cast<uint8_t>(value));
  }

  static FunctionTypePtr New(Heap::Space space);

  FINAL_HEAP_OBJECT_IMPLEMENTATION(FunctionType, AbstractType);
  friend class Class;
  friend class ClearTypeHashVisitor;
  friend class Function;
};

// A TypeRef is used to break cycles in the representation of recursive types.
// Its only field is the recursive AbstractType it refers to, which can
// temporarily be null during finalization.
// Note that the cycle always involves type arguments.
class TypeRef : public AbstractType {
 public:
  static intptr_t type_offset() { return OFFSET_OF(UntaggedTypeRef, type_); }

  virtual bool IsFinalized() const {
    const AbstractType& ref_type = AbstractType::Handle(type());
    return !ref_type.IsNull() && ref_type.IsFinalized();
  }
  virtual bool IsBeingFinalized() const {
    const AbstractType& ref_type = AbstractType::Handle(type());
    return ref_type.IsNull() || ref_type.IsBeingFinalized();
  }
  virtual Nullability nullability() const {
    const AbstractType& ref_type = AbstractType::Handle(type());
    ASSERT(!ref_type.IsNull());
    return ref_type.nullability();
  }
  virtual bool HasTypeClass() const {
    return (type() != AbstractType::null()) &&
           AbstractType::Handle(type()).HasTypeClass();
  }
  AbstractTypePtr type() const { return untag()->type(); }
  void set_type(const AbstractType& value) const;
  virtual classid_t type_class_id() const {
    return AbstractType::Handle(type()).type_class_id();
  }
  virtual ClassPtr type_class() const {
    return AbstractType::Handle(type()).type_class();
  }
  virtual TypeArgumentsPtr arguments() const {
    return AbstractType::Handle(type()).arguments();
  }
  virtual bool IsInstantiated(Genericity genericity = kAny,
                              intptr_t num_free_fun_type_params = kAllFree,
                              TrailPtr trail = nullptr) const;
  virtual bool IsEquivalent(const Instance& other,
                            TypeEquality kind,
                            TrailPtr trail = nullptr) const;
  virtual bool IsRecursive(TrailPtr trail = nullptr) const { return true; }
  virtual bool RequireConstCanonicalTypeErasure(Zone* zone,
                                                TrailPtr trail = nullptr) const;
  virtual AbstractTypePtr InstantiateFrom(
      const TypeArguments& instantiator_type_arguments,
      const TypeArguments& function_type_arguments,
      intptr_t num_free_fun_type_params,
      Heap::Space space,
      TrailPtr trail = nullptr) const;
  virtual AbstractTypePtr Canonicalize(Thread* thread, TrailPtr trail) const;
#if defined(DEBUG)
  // Check if typeref is canonical.
  virtual bool CheckIsCanonical(Thread* thread) const;
#endif  // DEBUG
  virtual void EnumerateURIs(URIs* uris) const;

  virtual uword Hash() const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedTypeRef));
  }

  static TypeRefPtr New(const AbstractType& type);

 private:
  static TypeRefPtr New();

  FINAL_HEAP_OBJECT_IMPLEMENTATION(TypeRef, AbstractType);
  friend class Class;
};

// A TypeParameter represents a type parameter of a parameterized class.
// It specifies its index (and its name for debugging purposes), as well as its
// upper bound.
// For example, the type parameter 'V' is specified as index 1 in the context of
// the class HashMap<K, V>. At compile time, the TypeParameter is not
// instantiated yet, i.e. it is only a place holder.
// Upon finalization, the TypeParameter index is changed to reflect its position
// as type argument (rather than type parameter) of the parameterized class.
// If the type parameter is declared without an extends clause, its bound is set
// to the ObjectType.
class TypeParameter : public AbstractType {
 public:
  virtual bool IsFinalized() const {
    return UntaggedTypeParameter::FinalizedBit::decode(untag()->flags_);
  }
  virtual void SetIsFinalized() const;
  virtual bool IsBeingFinalized() const {
    return UntaggedTypeParameter::BeingFinalizedBit::decode(untag()->flags_);
  }
  virtual void SetIsBeingFinalized() const;
  static intptr_t flags_offset() {
    return OFFSET_OF(UntaggedTypeParameter, flags_);
  }
  static intptr_t nullability_offset() {
    return OFFSET_OF(UntaggedTypeParameter, nullability_);
  }
  virtual Nullability nullability() const {
    return static_cast<Nullability>(untag()->nullability_);
  }
  TypeParameterPtr ToNullability(Nullability value, Heap::Space space) const;
  virtual bool HasTypeClass() const { return false; }
  virtual classid_t type_class_id() const { return kIllegalCid; }
  classid_t parameterized_class_id() const;
  void set_parameterized_class_id(classid_t value) const;
  ClassPtr parameterized_class() const;
  bool IsClassTypeParameter() const {
    return parameterized_class_id() != kFunctionCid;
  }
  bool IsFunctionTypeParameter() const {
    return parameterized_class_id() == kFunctionCid;
  }

  static intptr_t parameterized_class_id_offset() {
    return OFFSET_OF(UntaggedTypeParameter, parameterized_class_id_);
  }

  intptr_t base() const { return untag()->base_; }
  void set_base(intptr_t value) const;
  intptr_t index() const { return untag()->index_; }
  void set_index(intptr_t value) const;
  static intptr_t index_offset() {
    return OFFSET_OF(UntaggedTypeParameter, index_);
  }

  AbstractTypePtr bound() const { return untag()->bound(); }
  void set_bound(const AbstractType& value) const;
  static intptr_t bound_offset() {
    return OFFSET_OF(UntaggedTypeParameter, bound_);
  }

  virtual bool IsInstantiated(Genericity genericity = kAny,
                              intptr_t num_free_fun_type_params = kAllFree,
                              TrailPtr trail = nullptr) const;
  virtual bool IsEquivalent(const Instance& other,
                            TypeEquality kind,
                            TrailPtr trail = nullptr) const;
  virtual bool IsRecursive(TrailPtr trail = nullptr) const;
  virtual bool RequireConstCanonicalTypeErasure(
      Zone* zone,
      TrailPtr trail = nullptr) const {
    return IsNonNullable();
  }
  virtual AbstractTypePtr InstantiateFrom(
      const TypeArguments& instantiator_type_arguments,
      const TypeArguments& function_type_arguments,
      intptr_t num_free_fun_type_params,
      Heap::Space space,
      TrailPtr trail = nullptr) const;
  virtual AbstractTypePtr Canonicalize(Thread* thread, TrailPtr trail) const;
#if defined(DEBUG)
  // Check if type parameter is canonical.
  virtual bool CheckIsCanonical(Thread* thread) const;
#endif  // DEBUG
  virtual void EnumerateURIs(URIs* uris) const { return; }

  virtual uword Hash() const;

  // Returns type corresponding to [this] type parameter from the
  // given [instantiator_type_arguments] and [function_type_arguments].
  // Unlike InstantiateFrom, nullability of type parameter is not applied to
  // the result.
  AbstractTypePtr GetFromTypeArguments(
      const TypeArguments& instantiator_type_arguments,
      const TypeArguments& function_type_arguments) const;

  // Return a constructed name for this nameless type parameter.
  const char* CanonicalNameCString() const {
    return CanonicalNameCString(IsClassTypeParameter(), base(), index());
  }

  static const char* CanonicalNameCString(bool is_class_type_parameter,
                                          intptr_t base,
                                          intptr_t index);

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedTypeParameter));
  }

  // 'parameterized_class' is null for a function type parameter.
  static TypeParameterPtr New(const Class& parameterized_class,
                              intptr_t base,
                              intptr_t index,
                              const AbstractType& bound,
                              Nullability nullability);

 private:
  uword ComputeHash() const;
  void SetHash(intptr_t value) const;

  void set_parameterized_class(const Class& value) const;
  void set_name(const String& value) const;
  void set_flags(uint8_t flags) const;
  void set_nullability(Nullability value) const;

  static TypeParameterPtr New();

  FINAL_HEAP_OBJECT_IMPLEMENTATION(TypeParameter, AbstractType);
  friend class Class;
  friend class ClearTypeHashVisitor;
};

class Number : public Instance {
 public:
  // TODO(iposva): Add more useful Number methods.
  StringPtr ToString(Heap::Space space) const;

 private:
  OBJECT_IMPLEMENTATION(Number, Instance);

  friend class Class;
};

class Integer : public Number {
 public:
  static IntegerPtr New(const String& str, Heap::Space space = Heap::kNew);

  // Creates a new Integer by given uint64_t value.
  // Silently casts value to int64_t with wrap-around if it is greater
  // than kMaxInt64.
  static IntegerPtr NewFromUint64(uint64_t value,
                                  Heap::Space space = Heap::kNew);

  // Returns a canonical Integer object allocated in the old gen space.
  // Returns null if integer is out of range.
  static IntegerPtr NewCanonical(const String& str);
  static IntegerPtr NewCanonical(int64_t value);

  static IntegerPtr New(int64_t value, Heap::Space space = Heap::kNew);

  // Returns true iff the given uint64_t value is representable as Dart integer.
  static bool IsValueInRange(uint64_t value);

  virtual bool OperatorEquals(const Instance& other) const {
    return Equals(other);
  }
  virtual bool CanonicalizeEquals(const Instance& other) const {
    return Equals(other);
  }
  virtual uint32_t CanonicalizeHash() const { return AsTruncatedUint32Value(); }
  virtual bool Equals(const Instance& other) const;

  virtual ObjectPtr HashCode() const { return ptr(); }

  virtual bool IsZero() const;
  virtual bool IsNegative() const;

  virtual double AsDoubleValue() const;
  virtual int64_t AsInt64Value() const;
  virtual int64_t AsTruncatedInt64Value() const { return AsInt64Value(); }
  virtual uint32_t AsTruncatedUint32Value() const;

  virtual bool FitsIntoSmi() const;

  // Returns 0, -1 or 1.
  virtual int CompareWith(const Integer& other) const;

  // Converts integer to hex string.
  const char* ToHexCString(Zone* zone) const;

  // Return the most compact presentation of an integer.
  IntegerPtr AsValidInteger() const;

  // Returns null to indicate that a bigint operation is required.
  IntegerPtr ArithmeticOp(Token::Kind operation,
                          const Integer& other,
                          Heap::Space space = Heap::kNew) const;
  IntegerPtr BitOp(Token::Kind operation,
                   const Integer& other,
                   Heap::Space space = Heap::kNew) const;
  IntegerPtr ShiftOp(Token::Kind operation,
                     const Integer& other,
                     Heap::Space space = Heap::kNew) const;

  static int64_t GetInt64Value(const IntegerPtr obj) {
    if (obj->IsSmi()) {
      return RawSmiValue(static_cast<const SmiPtr>(obj));
    } else {
      ASSERT(obj->IsMint());
      return static_cast<const MintPtr>(obj)->untag()->value_;
    }
  }

 private:
  OBJECT_IMPLEMENTATION(Integer, Number);
  friend class Class;
};

class Smi : public Integer {
 public:
  static const intptr_t kBits = kSmiBits;
  static const intptr_t kMaxValue = kSmiMax;
  static const intptr_t kMinValue = kSmiMin;

  intptr_t Value() const { return RawSmiValue(ptr()); }

  virtual bool Equals(const Instance& other) const;
  virtual bool IsZero() const { return Value() == 0; }
  virtual bool IsNegative() const { return Value() < 0; }

  virtual double AsDoubleValue() const;
  virtual int64_t AsInt64Value() const;
  virtual uint32_t AsTruncatedUint32Value() const;

  virtual bool FitsIntoSmi() const { return true; }

  virtual int CompareWith(const Integer& other) const;

  static intptr_t InstanceSize() { return 0; }

  static SmiPtr New(intptr_t value) {
    SmiPtr raw_smi = static_cast<SmiPtr>(
        (static_cast<uintptr_t>(value) << kSmiTagShift) | kSmiTag);
    ASSERT(RawSmiValue(raw_smi) == value);
    return raw_smi;
  }

  static SmiPtr FromAlignedAddress(uword address) {
    ASSERT((address & kSmiTagMask) == kSmiTag);
    return static_cast<SmiPtr>(address);
  }

  static ClassPtr Class();

  static intptr_t Value(const SmiPtr raw_smi) { return RawSmiValue(raw_smi); }
#if defined(DART_COMPRESSED_POINTERS)
  static intptr_t Value(const CompressedSmiPtr raw_smi) {
    return Smi::Value(static_cast<SmiPtr>(raw_smi.DecompressSmi()));
  }
#endif

  static intptr_t RawValue(intptr_t value) {
    return static_cast<intptr_t>(New(value));
  }

  static bool IsValid(int64_t value) { return compiler::target::IsSmi(value); }

  void operator=(SmiPtr value) {
    ptr_ = value;
    CHECK_HANDLE();
  }
  void operator^=(ObjectPtr value) {
    ptr_ = value;
    CHECK_HANDLE();
  }

 private:
  static intptr_t NextFieldOffset() {
    // Indicates this class cannot be extended by dart code.
    return -kWordSize;
  }

  Smi() : Integer() {}
  BASE_OBJECT_IMPLEMENTATION(Smi, Integer);
  OBJECT_SERVICE_SUPPORT(Smi);
  friend class Api;  // For ValueFromRaw
  friend class Class;
  friend class Object;
  friend class ReusableSmiHandleScope;
  friend class Thread;
};

class SmiTraits : AllStatic {
 public:
  static const char* Name() { return "SmiTraits"; }
  static bool ReportStats() { return false; }

  static bool IsMatch(const Object& a, const Object& b) {
    return Smi::Cast(a).Value() == Smi::Cast(b).Value();
  }

  static uword Hash(const Object& obj) { return Smi::Cast(obj).Value(); }
};

class Mint : public Integer {
 public:
  static const intptr_t kBits = 63;  // 64-th bit is sign.
  static const int64_t kMaxValue =
      static_cast<int64_t>(DART_2PART_UINT64_C(0x7FFFFFFF, FFFFFFFF));
  static const int64_t kMinValue =
      static_cast<int64_t>(DART_2PART_UINT64_C(0x80000000, 00000000));

  int64_t value() const { return untag()->value_; }
  static intptr_t value_offset() { return OFFSET_OF(UntaggedMint, value_); }

  virtual bool IsZero() const { return value() == 0; }
  virtual bool IsNegative() const { return value() < 0; }

  virtual bool Equals(const Instance& other) const;

  virtual double AsDoubleValue() const;
  virtual int64_t AsInt64Value() const;
  virtual uint32_t AsTruncatedUint32Value() const;

  virtual bool FitsIntoSmi() const;

  virtual int CompareWith(const Integer& other) const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedMint));
  }

 protected:
  // Only Integer::NewXXX is allowed to call Mint::NewXXX directly.
  friend class Integer;
  friend class MintMessageDeserializationCluster;

  static MintPtr New(int64_t value, Heap::Space space = Heap::kNew);

  static MintPtr NewCanonical(int64_t value);

 private:
  void set_value(int64_t value) const;

  MINT_OBJECT_IMPLEMENTATION(Mint, Integer, Integer);
  friend class Class;
  friend class Number;
};

// Class Double represents class Double in corelib_impl, which implements
// abstract class double in corelib.
class Double : public Number {
 public:
  double value() const { return untag()->value_; }

  bool BitwiseEqualsToDouble(double value) const;
  virtual bool OperatorEquals(const Instance& other) const;
  virtual bool CanonicalizeEquals(const Instance& other) const;
  virtual uint32_t CanonicalizeHash() const;

  static DoublePtr New(double d, Heap::Space space = Heap::kNew);

  static DoublePtr New(const String& str, Heap::Space space = Heap::kNew);

  // Returns a canonical double object allocated in the old gen space.
  static DoublePtr NewCanonical(double d);

  // Returns a canonical double object (allocated in the old gen space) or
  // Double::null() if str points to a string that does not convert to a
  // double value.
  static DoublePtr NewCanonical(const String& str);

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedDouble));
  }

  static intptr_t value_offset() { return OFFSET_OF(UntaggedDouble, value_); }

 private:
  void set_value(double value) const;

  FINAL_HEAP_OBJECT_IMPLEMENTATION(Double, Number);
  friend class Class;
  friend class Number;
};

// TODO(http://dartbug.com/46716): Recognize Symbol in the VM.
class Symbol : public AllStatic {
 public:
  static bool IsSymbolCid(Thread* thread, classid_t class_id);

  static uint32_t CanonicalizeHash(Thread* thread, const Instance& instance);
};

// String may not be '\0' terminated.
class String : public Instance {
 public:
  static const intptr_t kOneByteChar = 1;
  static const intptr_t kTwoByteChar = 2;

// All strings share the same maximum element count to keep things
// simple.  We choose a value that will prevent integer overflow for
// 2 byte strings, since it is the worst case.
#if defined(HASH_IN_OBJECT_HEADER)
  static const intptr_t kSizeofRawString = sizeof(UntaggedInstance) + kWordSize;
#else
  static const intptr_t kSizeofRawString =
      sizeof(UntaggedInstance) + 2 * kWordSize;
#endif
  static const intptr_t kMaxElements = kSmiMax / kTwoByteChar;

  static intptr_t HeaderSize() { return String::kSizeofRawString; }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedString));
  }

  class CodePointIterator : public ValueObject {
   public:
    explicit CodePointIterator(const String& str)
        : str_(str), ch_(0), index_(-1), end_(str.Length()) {
      ASSERT(!str_.IsNull());
    }

    CodePointIterator(const String& str, intptr_t start, intptr_t length)
        : str_(str), ch_(0), index_(start - 1), end_(start + length) {
      ASSERT(start >= 0);
      ASSERT(end_ <= str.Length());
    }

    int32_t Current() const {
      ASSERT(index_ >= 0);
      ASSERT(index_ < end_);
      return ch_;
    }

    bool Next();

   private:
    const String& str_;
    int32_t ch_;
    intptr_t index_;
    intptr_t end_;
    DISALLOW_IMPLICIT_CONSTRUCTORS(CodePointIterator);
  };

  intptr_t Length() const { return LengthOf(ptr()); }
  static intptr_t LengthOf(StringPtr obj) {
    return Smi::Value(obj->untag()->length());
  }
  static intptr_t length_offset() { return OFFSET_OF(UntaggedString, length_); }

  uword Hash() const {
    uword result = GetCachedHash(ptr());
    if (result != 0) {
      return result;
    }
    result = String::Hash(*this, 0, this->Length());
    uword set_hash = SetCachedHashIfNotSet(ptr(), result);
    ASSERT(set_hash == result);
    return result;
  }

  static uword Hash(StringPtr raw);

  bool HasHash() const {
    ASSERT(Smi::New(0) == nullptr);
    return GetCachedHash(ptr()) != 0;
  }

  bool IsRecursive() const { return false; }  // Required by HashSet templates.

  static intptr_t hash_offset() {
#if defined(HASH_IN_OBJECT_HEADER)
    COMPILE_ASSERT(UntaggedObject::kHashTagPos % kBitsPerByte == 0);
    return OFFSET_OF(UntaggedObject, tags_) +
           UntaggedObject::kHashTagPos / kBitsPerByte;
#else
    return OFFSET_OF(UntaggedString, hash_);
#endif
  }
  static uword Hash(const String& str, intptr_t begin_index, intptr_t len);
  static uword Hash(const char* characters, intptr_t len);
  static uword Hash(const uint16_t* characters, intptr_t len);
  static uword Hash(const int32_t* characters, intptr_t len);
  static uword HashRawSymbol(const StringPtr symbol) {
    ASSERT(symbol->untag()->IsCanonical());
    const uword result = GetCachedHash(symbol);
    ASSERT(result != 0);
    return result;
  }

  // Returns the hash of str1 + str2.
  static uword HashConcat(const String& str1, const String& str2);

  virtual ObjectPtr HashCode() const { return Integer::New(Hash()); }

  uint16_t CharAt(intptr_t index) const { return CharAt(ptr(), index); }
  static uint16_t CharAt(StringPtr str, intptr_t index);

  intptr_t CharSize() const;

  inline bool Equals(const String& str) const;

  bool Equals(const String& str,
              intptr_t begin_index,  // begin index on 'str'.
              intptr_t len) const;   // len on 'str'.

  // Compares to a '\0' terminated array of UTF-8 encoded characters.
  bool Equals(const char* cstr) const;

  // Compares to an array of Latin-1 encoded characters.
  bool EqualsLatin1(const uint8_t* characters, intptr_t len) const {
    return Equals(characters, len);
  }

  // Compares to an array of UTF-16 encoded characters.
  bool Equals(const uint16_t* characters, intptr_t len) const;

  // Compares to an array of UTF-32 encoded characters.
  bool Equals(const int32_t* characters, intptr_t len) const;

  // True iff this string equals str1 + str2.
  bool EqualsConcat(const String& str1, const String& str2) const;

  virtual bool OperatorEquals(const Instance& other) const {
    return Equals(other);
  }
  virtual bool CanonicalizeEquals(const Instance& other) const {
    return Equals(other);
  }
  virtual uint32_t CanonicalizeHash() const { return Hash(); }
  virtual bool Equals(const Instance& other) const;

  intptr_t CompareTo(const String& other) const;

  bool StartsWith(const String& other) const {
    NoSafepointScope no_safepoint;
    return StartsWith(ptr(), other.ptr());
  }
  static bool StartsWith(StringPtr str, StringPtr prefix);
  bool EndsWith(const String& other) const;

  // Strings are canonicalized using the symbol table.
  // Caller must hold IsolateGroup::constant_canonicalization_mutex_.
  virtual InstancePtr CanonicalizeLocked(Thread* thread) const;

#if defined(DEBUG)
  // Check if string is canonical.
  virtual bool CheckIsCanonical(Thread* thread) const;
#endif  // DEBUG

  bool IsSymbol() const { return ptr()->untag()->IsCanonical(); }

  bool IsOneByteString() const {
    return ptr()->GetClassId() == kOneByteStringCid;
  }

  bool IsTwoByteString() const {
    return ptr()->GetClassId() == kTwoByteStringCid;
  }

  bool IsExternalOneByteString() const {
    return ptr()->GetClassId() == kExternalOneByteStringCid;
  }

  bool IsExternalTwoByteString() const {
    return ptr()->GetClassId() == kExternalTwoByteStringCid;
  }

  bool IsExternal() const {
    return IsExternalStringClassId(ptr()->GetClassId());
  }

  void* GetPeer() const;

  char* ToMallocCString() const;
  void ToUTF8(uint8_t* utf8_array, intptr_t array_len) const;
  static const char* ToCString(Thread* thread, StringPtr ptr);

  // Creates a new String object from a C string that is assumed to contain
  // UTF-8 encoded characters and '\0' is considered a termination character.
  // TODO(7123) - Rename this to FromCString(....).
  static StringPtr New(const char* cstr, Heap::Space space = Heap::kNew);

  // Creates a new String object from an array of UTF-8 encoded characters.
  static StringPtr FromUTF8(const uint8_t* utf8_array,
                            intptr_t array_len,
                            Heap::Space space = Heap::kNew);

  // Creates a new String object from an array of Latin-1 encoded characters.
  static StringPtr FromLatin1(const uint8_t* latin1_array,
                              intptr_t array_len,
                              Heap::Space space = Heap::kNew);

  // Creates a new String object from an array of UTF-16 encoded characters.
  static StringPtr FromUTF16(const uint16_t* utf16_array,
                             intptr_t array_len,
                             Heap::Space space = Heap::kNew);

  // Creates a new String object from an array of UTF-32 encoded characters.
  static StringPtr FromUTF32(const int32_t* utf32_array,
                             intptr_t array_len,
                             Heap::Space space = Heap::kNew);

  // Create a new String object from another Dart String instance.
  static StringPtr New(const String& str, Heap::Space space = Heap::kNew);

  // Creates a new External String object using the specified array of
  // UTF-8 encoded characters as the external reference.
  static StringPtr NewExternal(const uint8_t* utf8_array,
                               intptr_t array_len,
                               void* peer,
                               intptr_t external_allocation_size,
                               Dart_HandleFinalizer callback,
                               Heap::Space = Heap::kNew);

  // Creates a new External String object using the specified array of
  // UTF-16 encoded characters as the external reference.
  static StringPtr NewExternal(const uint16_t* utf16_array,
                               intptr_t array_len,
                               void* peer,
                               intptr_t external_allocation_size,
                               Dart_HandleFinalizer callback,
                               Heap::Space = Heap::kNew);

  static void Copy(const String& dst,
                   intptr_t dst_offset,
                   const uint8_t* characters,
                   intptr_t len);
  static void Copy(const String& dst,
                   intptr_t dst_offset,
                   const uint16_t* characters,
                   intptr_t len);
  static void Copy(const String& dst,
                   intptr_t dst_offset,
                   const String& src,
                   intptr_t src_offset,
                   intptr_t len);

  static StringPtr EscapeSpecialCharacters(const String& str);
  // Encodes 'str' for use in an Internationalized Resource Identifier (IRI),
  // a generalization of URI (percent-encoding). See RFC 3987.
  static const char* EncodeIRI(const String& str);
  // Returns null if 'str' is not a valid encoding.
  static StringPtr DecodeIRI(const String& str);
  static StringPtr Concat(const String& str1,
                          const String& str2,
                          Heap::Space space = Heap::kNew);
  static StringPtr ConcatAll(const Array& strings,
                             Heap::Space space = Heap::kNew);
  // Concat all strings in 'strings' from 'start' to 'end' (excluding).
  static StringPtr ConcatAllRange(const Array& strings,
                                  intptr_t start,
                                  intptr_t end,
                                  Heap::Space space = Heap::kNew);

  static StringPtr SubString(const String& str,
                             intptr_t begin_index,
                             Heap::Space space = Heap::kNew);
  static StringPtr SubString(const String& str,
                             intptr_t begin_index,
                             intptr_t length,
                             Heap::Space space = Heap::kNew) {
    return SubString(Thread::Current(), str, begin_index, length, space);
  }
  static StringPtr SubString(Thread* thread,
                             const String& str,
                             intptr_t begin_index,
                             intptr_t length,
                             Heap::Space space = Heap::kNew);

  static StringPtr Transform(int32_t (*mapping)(int32_t ch),
                             const String& str,
                             Heap::Space space = Heap::kNew);

  static StringPtr ToUpperCase(const String& str,
                               Heap::Space space = Heap::kNew);
  static StringPtr ToLowerCase(const String& str,
                               Heap::Space space = Heap::kNew);

  static StringPtr RemovePrivateKey(const String& name);

  static const char* ScrubName(const String& name, bool is_extension = false);
  static StringPtr ScrubNameRetainPrivate(const String& name,
                                          bool is_extension = false);

  static bool EqualsIgnoringPrivateKey(const String& str1, const String& str2);

  static StringPtr NewFormatted(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
  static StringPtr NewFormatted(Heap::Space space, const char* format, ...)
      PRINTF_ATTRIBUTE(2, 3);
  static StringPtr NewFormattedV(const char* format,
                                 va_list args,
                                 Heap::Space space = Heap::kNew);

  static bool ParseDouble(const String& str,
                          intptr_t start,
                          intptr_t end,
                          double* result);

#if !defined(HASH_IN_OBJECT_HEADER)
  static uint32_t GetCachedHash(const StringPtr obj) {
    return Smi::Value(obj->untag()->hash_);
  }

  static uint32_t SetCachedHashIfNotSet(StringPtr obj, uint32_t hash) {
    ASSERT(Smi::Value(obj->untag()->hash_) == 0 ||
           Smi::Value(obj->untag()->hash_) == static_cast<intptr_t>(hash));
    return SetCachedHash(obj, hash);
  }
  static uint32_t SetCachedHash(StringPtr obj, uint32_t hash) {
    obj->untag()->hash_ = Smi::New(hash);
    return hash;
  }
#else
  static uint32_t SetCachedHash(StringPtr obj, uint32_t hash) {
    return Object::SetCachedHashIfNotSet(obj, hash);
  }
#endif

 protected:
  // These two operate on an array of Latin-1 encoded characters.
  // They are protected to avoid mistaking Latin-1 for UTF-8, but used
  // by friendly templated code (e.g., Symbols).
  bool Equals(const uint8_t* characters, intptr_t len) const;
  static uword Hash(const uint8_t* characters, intptr_t len);

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

  void SetHash(intptr_t value) const {
    const intptr_t hash_set = SetCachedHashIfNotSet(ptr(), value);
    ASSERT(hash_set == value);
  }

  FINAL_HEAP_OBJECT_IMPLEMENTATION(String, Instance);

  friend class Class;
  friend class Symbols;
  friend class StringSlice;  // SetHash
  template <typename CharType>
  friend class CharArray;     // SetHash
  friend class ConcatString;  // SetHash
  friend class OneByteString;
  friend class TwoByteString;
  friend class ExternalOneByteString;
  friend class ExternalTwoByteString;
  friend class UntaggedOneByteString;
  friend class RODataSerializationCluster;  // SetHash
  friend class Pass2Visitor;                // Stack "handle"
};

// Synchronize with implementation in compiler (intrinsifier).
class StringHasher : public ValueObject {
 public:
  StringHasher() : hash_(0) {}
  void Add(uint16_t code_unit) { hash_ = CombineHashes(hash_, code_unit); }
  void Add(const uint8_t* code_units, intptr_t len) {
    while (len > 0) {
      Add(*code_units);
      code_units++;
      len--;
    }
  }
  void Add(const uint16_t* code_units, intptr_t len) {
    while (len > 0) {
      Add(LoadUnaligned(code_units));
      code_units++;
      len--;
    }
  }
  void Add(const String& str, intptr_t begin_index, intptr_t len);
  intptr_t Finalize() { return FinalizeHash(hash_, String::kHashBits); }

 private:
  uint32_t hash_;
};

class OneByteString : public AllStatic {
 public:
  ALLSTATIC_CONTAINS_COMPRESSED_IMPLEMENTATION(OneByteString, String);

  static uint16_t CharAt(const String& str, intptr_t index) {
    ASSERT(str.IsOneByteString());
    NoSafepointScope no_safepoint;
    return OneByteString::CharAt(static_cast<OneByteStringPtr>(str.ptr()),
                                 index);
  }

  static uint16_t CharAt(OneByteStringPtr str, intptr_t index) {
    ASSERT(index >= 0 && index < String::LengthOf(str));
    return str->untag()->data()[index];
  }

  static void SetCharAt(const String& str, intptr_t index, uint8_t code_unit) {
    NoSafepointScope no_safepoint;
    *CharAddr(str, index) = code_unit;
  }
  static OneByteStringPtr EscapeSpecialCharacters(const String& str);
  // We use the same maximum elements for all strings.
  static const intptr_t kBytesPerElement = 1;
  static const intptr_t kMaxElements = String::kMaxElements;

  struct ArrayTraits {
    static intptr_t elements_start_offset() {
      return sizeof(UntaggedOneByteString);
    }
    static constexpr intptr_t kElementSize = kBytesPerElement;
  };

  static intptr_t data_offset() {
    return OFFSET_OF_RETURNED_VALUE(UntaggedOneByteString, data);
  }

  static intptr_t UnroundedSize(OneByteStringPtr str) {
    return UnroundedSize(Smi::Value(str->untag()->length()));
  }
  static intptr_t UnroundedSize(intptr_t len) {
    return sizeof(UntaggedOneByteString) + (len * kBytesPerElement);
  }
  static intptr_t InstanceSize() {
    ASSERT(sizeof(UntaggedOneByteString) ==
           OFFSET_OF_RETURNED_VALUE(UntaggedOneByteString, data));
    return 0;
  }
  static intptr_t InstanceSize(intptr_t len) {
    ASSERT(sizeof(UntaggedOneByteString) == String::kSizeofRawString);
    ASSERT(0 <= len && len <= kMaxElements);
    return String::RoundedAllocationSize(UnroundedSize(len));
  }

  static OneByteStringPtr New(intptr_t len, Heap::Space space);
  static OneByteStringPtr New(const char* c_string,
                              Heap::Space space = Heap::kNew) {
    return New(reinterpret_cast<const uint8_t*>(c_string), strlen(c_string),
               space);
  }
  static OneByteStringPtr New(const uint8_t* characters,
                              intptr_t len,
                              Heap::Space space);
  static OneByteStringPtr New(const uint16_t* characters,
                              intptr_t len,
                              Heap::Space space);
  static OneByteStringPtr New(const int32_t* characters,
                              intptr_t len,
                              Heap::Space space);
  static OneByteStringPtr New(const String& str, Heap::Space space);
  // 'other' must be OneByteString.
  static OneByteStringPtr New(const String& other_one_byte_string,
                              intptr_t other_start_index,
                              intptr_t other_len,
                              Heap::Space space);

  static OneByteStringPtr New(const TypedDataBase& other_typed_data,
                              intptr_t other_start_index,
                              intptr_t other_len,
                              Heap::Space space = Heap::kNew);

  static OneByteStringPtr Concat(const String& str1,
                                 const String& str2,
                                 Heap::Space space);
  static OneByteStringPtr ConcatAll(const Array& strings,
                                    intptr_t start,
                                    intptr_t end,
                                    intptr_t len,
                                    Heap::Space space);

  static OneByteStringPtr Transform(int32_t (*mapping)(int32_t ch),
                                    const String& str,
                                    Heap::Space space);

  // High performance version of substring for one-byte strings.
  // "str" must be OneByteString.
  static OneByteStringPtr SubStringUnchecked(const String& str,
                                             intptr_t begin_index,
                                             intptr_t length,
                                             Heap::Space space);

  static const ClassId kClassId = kOneByteStringCid;

  static OneByteStringPtr null() {
    return static_cast<OneByteStringPtr>(Object::null());
  }

 private:
  static OneByteStringPtr raw(const String& str) {
    return static_cast<OneByteStringPtr>(str.ptr());
  }

  static const UntaggedOneByteString* untag(const String& str) {
    return reinterpret_cast<const UntaggedOneByteString*>(str.untag());
  }

  static uint8_t* CharAddr(const String& str, intptr_t index) {
    ASSERT((index >= 0) && (index < str.Length()));
    ASSERT(str.IsOneByteString());
    return &str.UnsafeMutableNonPointer(untag(str)->data())[index];
  }

  static uint8_t* DataStart(const String& str) {
    ASSERT(str.IsOneByteString());
    return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
  }

  friend class Class;
  friend class ExternalOneByteString;
  friend class ImageWriter;
  friend class String;
  friend class StringHasher;
  friend class Symbols;
  friend class Utf8;
  friend class OneByteStringMessageSerializationCluster;
  friend class Deserializer;
};

class TwoByteString : public AllStatic {
 public:
  ALLSTATIC_CONTAINS_COMPRESSED_IMPLEMENTATION(TwoByteString, String);

  static uint16_t CharAt(const String& str, intptr_t index) {
    ASSERT(str.IsTwoByteString());
    NoSafepointScope no_safepoint;
    return TwoByteString::CharAt(static_cast<TwoByteStringPtr>(str.ptr()),
                                 index);
  }

  static uint16_t CharAt(TwoByteStringPtr str, intptr_t index) {
    ASSERT(index >= 0 && index < String::LengthOf(str));
    return str->untag()->data()[index];
  }

  static void SetCharAt(const String& str, intptr_t index, uint16_t ch) {
    NoSafepointScope no_safepoint;
    *CharAddr(str, index) = ch;
  }

  static TwoByteStringPtr EscapeSpecialCharacters(const String& str);

  // We use the same maximum elements for all strings.
  static const intptr_t kBytesPerElement = 2;
  static const intptr_t kMaxElements = String::kMaxElements;

  struct ArrayTraits {
    static intptr_t elements_start_offset() {
      return sizeof(UntaggedTwoByteString);
    }
    static constexpr intptr_t kElementSize = kBytesPerElement;
  };

  static intptr_t data_offset() {
    return OFFSET_OF_RETURNED_VALUE(UntaggedTwoByteString, data);
  }
  static intptr_t UnroundedSize(TwoByteStringPtr str) {
    return UnroundedSize(Smi::Value(str->untag()->length()));
  }
  static intptr_t UnroundedSize(intptr_t len) {
    return sizeof(UntaggedTwoByteString) + (len * kBytesPerElement);
  }
  static intptr_t InstanceSize() {
    ASSERT(sizeof(UntaggedTwoByteString) ==
           OFFSET_OF_RETURNED_VALUE(UntaggedTwoByteString, data));
    return 0;
  }
  static intptr_t InstanceSize(intptr_t len) {
    ASSERT(sizeof(UntaggedTwoByteString) == String::kSizeofRawString);
    ASSERT(0 <= len && len <= kMaxElements);
    return String::RoundedAllocationSize(UnroundedSize(len));
  }

  static TwoByteStringPtr New(intptr_t len, Heap::Space space);
  static TwoByteStringPtr New(const uint16_t* characters,
                              intptr_t len,
                              Heap::Space space);
  static TwoByteStringPtr New(intptr_t utf16_len,
                              const int32_t* characters,
                              intptr_t len,
                              Heap::Space space);
  static TwoByteStringPtr New(const String& str, Heap::Space space);

  static TwoByteStringPtr New(const TypedDataBase& other_typed_data,
                              intptr_t other_start_index,
                              intptr_t other_len,
                              Heap::Space space = Heap::kNew);

  static TwoByteStringPtr Concat(const String& str1,
                                 const String& str2,
                                 Heap::Space space);
  static TwoByteStringPtr ConcatAll(const Array& strings,
                                    intptr_t start,
                                    intptr_t end,
                                    intptr_t len,
                                    Heap::Space space);

  static TwoByteStringPtr Transform(int32_t (*mapping)(int32_t ch),
                                    const String& str,
                                    Heap::Space space);

  static TwoByteStringPtr null() {
    return static_cast<TwoByteStringPtr>(Object::null());
  }

  static const ClassId kClassId = kTwoByteStringCid;

 private:
  static TwoByteStringPtr raw(const String& str) {
    return static_cast<TwoByteStringPtr>(str.ptr());
  }

  static const UntaggedTwoByteString* untag(const String& str) {
    return reinterpret_cast<const UntaggedTwoByteString*>(str.untag());
  }

  static uint16_t* CharAddr(const String& str, intptr_t index) {
    ASSERT((index >= 0) && (index < str.Length()));
    ASSERT(str.IsTwoByteString());
    return &str.UnsafeMutableNonPointer(untag(str)->data())[index];
  }

  // Use this instead of CharAddr(0).  It will not assert that the index is <
  // length.
  static uint16_t* DataStart(const String& str) {
    ASSERT(str.IsTwoByteString());
    return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
  }

  friend class Class;
  friend class ImageWriter;
  friend class String;
  friend class StringHasher;
  friend class Symbols;
  friend class TwoByteStringMessageSerializationCluster;
};

class ExternalOneByteString : public AllStatic {
 public:
  ALLSTATIC_CONTAINS_COMPRESSED_IMPLEMENTATION(ExternalOneByteString, String);

  static uint16_t CharAt(const String& str, intptr_t index) {
    ASSERT(str.IsExternalOneByteString());
    NoSafepointScope no_safepoint;
    return ExternalOneByteString::CharAt(
        static_cast<ExternalOneByteStringPtr>(str.ptr()), index);
  }

  static uint16_t CharAt(ExternalOneByteStringPtr str, intptr_t index) {
    ASSERT(index >= 0 && index < String::LengthOf(str));
    return str->untag()->external_data_[index];
  }

  static void* GetPeer(const String& str) { return untag(str)->peer_; }

  static intptr_t external_data_offset() {
    return OFFSET_OF(UntaggedExternalOneByteString, external_data_);
  }

  // We use the same maximum elements for all strings.
  static const intptr_t kBytesPerElement = 1;
  static const intptr_t kMaxElements = String::kMaxElements;

  static intptr_t InstanceSize() {
    return String::RoundedAllocationSize(sizeof(UntaggedExternalOneByteString));
  }

  static ExternalOneByteStringPtr New(const uint8_t* characters,
                                      intptr_t len,
                                      void* peer,
                                      intptr_t external_allocation_size,
                                      Dart_HandleFinalizer callback,
                                      Heap::Space space);

  static ExternalOneByteStringPtr null() {
    return static_cast<ExternalOneByteStringPtr>(Object::null());
  }

  static OneByteStringPtr EscapeSpecialCharacters(const String& str);
  static OneByteStringPtr EncodeIRI(const String& str);
  static OneByteStringPtr DecodeIRI(const String& str);

  static const ClassId kClassId = kExternalOneByteStringCid;

 private:
  static ExternalOneByteStringPtr raw(const String& str) {
    return static_cast<ExternalOneByteStringPtr>(str.ptr());
  }

  static const UntaggedExternalOneByteString* untag(const String& str) {
    return reinterpret_cast<const UntaggedExternalOneByteString*>(str.untag());
  }

  static const uint8_t* CharAddr(const String& str, intptr_t index) {
    ASSERT((index >= 0) && (index < str.Length()));
    ASSERT(str.IsExternalOneByteString());
    return &(untag(str)->external_data_[index]);
  }

  static const uint8_t* DataStart(const String& str) {
    ASSERT(str.IsExternalOneByteString());
    return untag(str)->external_data_;
  }

  static void SetExternalData(const String& str,
                              const uint8_t* data,
                              void* peer) {
    ASSERT(str.IsExternalOneByteString());
    ASSERT(!IsolateGroup::Current()->heap()->Contains(
        reinterpret_cast<uword>(data)));
    str.StoreNonPointer(&untag(str)->external_data_, data);
    str.StoreNonPointer(&untag(str)->peer_, peer);
  }

  static void Finalize(void* isolate_callback_data,
                       Dart_WeakPersistentHandle handle,
                       void* peer);

  static intptr_t NextFieldOffset() {
    // Indicates this class cannot be extended by dart code.
    return -kWordSize;
  }

  friend class Class;
  friend class String;
  friend class StringHasher;
  friend class Symbols;
  friend class Utf8;
};

class ExternalTwoByteString : public AllStatic {
 public:
  ALLSTATIC_CONTAINS_COMPRESSED_IMPLEMENTATION(ExternalTwoByteString, String);

  static uint16_t CharAt(const String& str, intptr_t index) {
    ASSERT(str.IsExternalTwoByteString());
    NoSafepointScope no_safepoint;
    return ExternalTwoByteString::CharAt(
        static_cast<ExternalTwoByteStringPtr>(str.ptr()), index);
  }

  static uint16_t CharAt(ExternalTwoByteStringPtr str, intptr_t index) {
    ASSERT(index >= 0 && index < String::LengthOf(str));
    return str->untag()->external_data_[index];
  }

  static void* GetPeer(const String& str) { return untag(str)->peer_; }

  static intptr_t external_data_offset() {
    return OFFSET_OF(UntaggedExternalTwoByteString, external_data_);
  }

  // We use the same maximum elements for all strings.
  static const intptr_t kBytesPerElement = 2;
  static const intptr_t kMaxElements = String::kMaxElements;

  static intptr_t InstanceSize() {
    return String::RoundedAllocationSize(sizeof(UntaggedExternalTwoByteString));
  }

  static ExternalTwoByteStringPtr New(const uint16_t* characters,
                                      intptr_t len,
                                      void* peer,
                                      intptr_t external_allocation_size,
                                      Dart_HandleFinalizer callback,
                                      Heap::Space space = Heap::kNew);

  static ExternalTwoByteStringPtr null() {
    return static_cast<ExternalTwoByteStringPtr>(Object::null());
  }

  static const ClassId kClassId = kExternalTwoByteStringCid;

 private:
  static ExternalTwoByteStringPtr raw(const String& str) {
    return static_cast<ExternalTwoByteStringPtr>(str.ptr());
  }

  static const UntaggedExternalTwoByteString* untag(const String& str) {
    return reinterpret_cast<const UntaggedExternalTwoByteString*>(str.untag());
  }

  static const uint16_t* CharAddr(const String& str, intptr_t index) {
    ASSERT((index >= 0) && (index < str.Length()));
    ASSERT(str.IsExternalTwoByteString());
    return &(untag(str)->external_data_[index]);
  }

  static const uint16_t* DataStart(const String& str) {
    ASSERT(str.IsExternalTwoByteString());
    return untag(str)->external_data_;
  }

  static void SetExternalData(const String& str,
                              const uint16_t* data,
                              void* peer) {
    ASSERT(str.IsExternalTwoByteString());
    ASSERT(!IsolateGroup::Current()->heap()->Contains(
        reinterpret_cast<uword>(data)));
    str.StoreNonPointer(&untag(str)->external_data_, data);
    str.StoreNonPointer(&untag(str)->peer_, peer);
  }

  static void Finalize(void* isolate_callback_data,
                       Dart_WeakPersistentHandle handle,
                       void* peer);

  static intptr_t NextFieldOffset() {
    // Indicates this class cannot be extended by dart code.
    return -kWordSize;
  }

  friend class Class;
  friend class String;
  friend class StringHasher;
  friend class Symbols;
};

// Matches null_patch.dart / bool_patch.dart.
static constexpr intptr_t kNullIdentityHash = 2011;
static constexpr intptr_t kTrueIdentityHash = 1231;
static constexpr intptr_t kFalseIdentityHash = 1237;

// Class Bool implements Dart core class bool.
class Bool : public Instance {
 public:
  bool value() const { return untag()->value_; }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedBool));
  }

  static const Bool& True() { return Object::bool_true(); }

  static const Bool& False() { return Object::bool_false(); }

  static const Bool& Get(bool value) {
    return value ? Bool::True() : Bool::False();
  }

  virtual uint32_t CanonicalizeHash() const {
    return ptr() == True().ptr() ? kTrueIdentityHash : kFalseIdentityHash;
  }

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(Bool, Instance);
  friend class Class;
  friend class Object;  // To initialize the true and false values.
};

class Array : public Instance {
 public:
  // Returns `true` if we use card marking for arrays of length [array_length].
  static constexpr bool UseCardMarkingForAllocation(
      const intptr_t array_length) {
    return Array::InstanceSize(array_length) > Heap::kNewAllocatableSize;
  }

  // WB invariant restoration code only applies to arrives which have at most
  // this many elements. Consequently WB elimination code should not eliminate
  // WB on arrays of larger lengths across instructions that can cause GC.
  // Note: we also can't restore WB invariant for arrays which use card marking.
  static constexpr intptr_t kMaxLengthForWriteBarrierElimination = 8;

  intptr_t Length() const { return LengthOf(ptr()); }
  static intptr_t LengthOf(const ArrayPtr array) {
    return Smi::Value(array->untag()->length());
  }

  static intptr_t length_offset() { return OFFSET_OF(UntaggedArray, length_); }
  static intptr_t data_offset() {
    return OFFSET_OF_RETURNED_VALUE(UntaggedArray, data);
  }
  static intptr_t element_offset(intptr_t index) {
    return OFFSET_OF_RETURNED_VALUE(UntaggedArray, data) +
           kBytesPerElement * index;
  }
  static intptr_t index_at_offset(intptr_t offset_in_bytes) {
    intptr_t index = (offset_in_bytes - data_offset()) / kBytesPerElement;
    ASSERT(index >= 0);
    return index;
  }

  struct ArrayTraits {
    static intptr_t elements_start_offset() { return Array::data_offset(); }

    static constexpr intptr_t kElementSize = kCompressedWordSize;
  };

  static bool Equals(ArrayPtr a, ArrayPtr b) {
    if (a == b) return true;
    if (a->IsRawNull() || b->IsRawNull()) return false;
    if (a->untag()->length() != b->untag()->length()) return false;
    if (a->untag()->type_arguments() != b->untag()->type_arguments()) {
      return false;
    }
    const intptr_t length = LengthOf(a);
    return memcmp(a->untag()->data(), b->untag()->data(),
                  kBytesPerElement * length) == 0;
  }
  bool Equals(const Array& other) const {
    NoSafepointScope scope;
    return Equals(ptr(), other.ptr());
  }

  static CompressedObjectPtr* DataOf(ArrayPtr array) {
    return array->untag()->data();
  }

  template <std::memory_order order = std::memory_order_relaxed>
  ObjectPtr At(intptr_t index) const {
    return untag()->element<order>(index);
  }
  template <std::memory_order order = std::memory_order_relaxed>
  void SetAt(intptr_t index, const Object& value) const {
    // TODO(iposva): Add storing NoSafepointScope.
    untag()->set_element<order>(index, value.ptr());
  }

  // Access to the array with acquire release semantics.
  ObjectPtr AtAcquire(intptr_t index) const {
    return untag()->element<std::memory_order_acquire>(index);
  }
  void SetAtRelease(intptr_t index, const Object& value) const {
    untag()->set_element<std::memory_order_release>(index, value.ptr());
  }

  bool IsImmutable() const { return ptr()->GetClassId() == kImmutableArrayCid; }

  // Position of element type in type arguments.
  static const intptr_t kElementTypeTypeArgPos = 0;

  virtual TypeArgumentsPtr GetTypeArguments() const {
    return untag()->type_arguments();
  }
  virtual void SetTypeArguments(const TypeArguments& value) const {
    // An Array is raw or takes one type argument. However, its type argument
    // vector may be longer than 1 due to a type optimization reusing the type
    // argument vector of the instantiator.
    ASSERT(value.IsNull() ||
           ((value.Length() >= 1) &&
            value.IsInstantiated() /*&& value.IsCanonical()*/));
    // TODO(asiva): Values read from a message snapshot are not properly marked
    // as canonical. See for example tests/isolate/mandel_isolate_test.dart.
    StoreArrayPointer(&untag()->type_arguments_, value.ptr());
  }

  virtual bool CanonicalizeEquals(const Instance& other) const;
  virtual uint32_t CanonicalizeHash() const;

  static const intptr_t kBytesPerElement = ArrayTraits::kElementSize;
  static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
  static const intptr_t kMaxNewSpaceElements =
      (Heap::kNewAllocatableSize - sizeof(UntaggedArray)) / kBytesPerElement;

  static intptr_t type_arguments_offset() {
    return OFFSET_OF(UntaggedArray, type_arguments_);
  }

  static constexpr bool IsValidLength(intptr_t len) {
    return 0 <= len && len <= kMaxElements;
  }

  static intptr_t InstanceSize() {
    ASSERT(sizeof(UntaggedArray) ==
           OFFSET_OF_RETURNED_VALUE(UntaggedArray, data));
    return 0;
  }

  static constexpr intptr_t InstanceSize(intptr_t len) {
    // Ensure that variable length data is not adding to the object length.
    ASSERT(sizeof(UntaggedArray) ==
           (sizeof(UntaggedInstance) + (2 * kBytesPerElement)));
    ASSERT(IsValidLength(len));
    return RoundedAllocationSize(sizeof(UntaggedArray) +
                                 (len * kBytesPerElement));
  }

  virtual void CanonicalizeFieldsLocked(Thread* thread) const;

  // Make the array immutable to Dart code by switching the class pointer
  // to ImmutableArray.
  void MakeImmutable() const;

  static ArrayPtr New(intptr_t len, Heap::Space space = Heap::kNew);
  static ArrayPtr New(intptr_t len,
                      const AbstractType& element_type,
                      Heap::Space space = Heap::kNew);

  // Creates and returns a new array with 'new_length'. Copies all elements from
  // 'source' to the new array. 'new_length' must be greater than or equal to
  // 'source.Length()'. 'source' can be null.
  static ArrayPtr Grow(const Array& source,
                       intptr_t new_length,
                       Heap::Space space = Heap::kNew);

  // Truncates the array to a given length. 'new_length' must be less than
  // or equal to 'source.Length()'. The remaining unused part of the array is
  // marked as an Array object or a regular Object so that it can be traversed
  // during garbage collection.
  void Truncate(intptr_t new_length) const;

  // Return an Array object that contains all the elements currently present
  // in the specified Growable Object Array. This is done by first truncating
  // the Growable Object Array's backing array to the currently used size and
  // returning the truncated backing array.
  // The backing array of the original Growable Object Array is
  // set to an empty array.
  // If the unique parameter is false, the function is allowed to return
  // a shared Array instance.
  static ArrayPtr MakeFixedLength(const GrowableObjectArray& growable_array,
                                  bool unique = false);

  ArrayPtr Slice(intptr_t start, intptr_t count, bool with_type_argument) const;
  ArrayPtr Copy() const {
    return Slice(0, Length(), /*with_type_argument=*/true);
  }

 protected:
  static ArrayPtr New(intptr_t class_id,
                      intptr_t len,
                      Heap::Space space = Heap::kNew);

 private:
  CompressedObjectPtr const* ObjectAddr(intptr_t index) const {
    // TODO(iposva): Determine if we should throw an exception here.
    ASSERT((index >= 0) && (index < Length()));
    return &untag()->data()[index];
  }

  void SetLength(intptr_t value) const { untag()->set_length(Smi::New(value)); }
  void SetLengthRelease(intptr_t value) const {
    untag()->set_length<std::memory_order_release>(Smi::New(value));
  }

  template <typename type,
            std::memory_order order = std::memory_order_relaxed,
            typename value_type>
  void StoreArrayPointer(type const* addr, value_type value) const {
    ptr()->untag()->StoreArrayPointer<type, order, value_type>(addr, value);
  }

  // Store a range of pointers [from, from + count) into [to, to + count).
  // TODO(koda): Use this to fix Object::Clone's broken store buffer logic.
  void StoreArrayPointers(CompressedObjectPtr const* to,
                          CompressedObjectPtr const* from,
                          intptr_t count) {
    ASSERT(Contains(reinterpret_cast<uword>(to)));
    if (ptr()->IsNewObject()) {
      memmove(const_cast<CompressedObjectPtr*>(to), from,
              count * kBytesPerElement);
    } else {
      const uword heap_base = ptr()->heap_base();
      for (intptr_t i = 0; i < count; ++i) {
        StoreArrayPointer(&to[i], from[i].Decompress(heap_base));
      }
    }
  }

  FINAL_HEAP_OBJECT_IMPLEMENTATION(Array, Instance);
  friend class Class;
  friend class ImmutableArray;
  friend class Object;
  friend class String;
  friend class MessageDeserializer;
};

class ImmutableArray : public AllStatic {
 public:
  static constexpr bool ContainsCompressedPointers() {
    return Array::ContainsCompressedPointers();
  }

  static ImmutableArrayPtr New(intptr_t len, Heap::Space space = Heap::kNew);

  static const ClassId kClassId = kImmutableArrayCid;

  static intptr_t InstanceSize() { return Array::InstanceSize(); }

  static intptr_t InstanceSize(intptr_t len) {
    return Array::InstanceSize(len);
  }

 private:
  static intptr_t NextFieldOffset() {
    // Indicates this class cannot be extended by dart code.
    return -kWordSize;
  }

  static ImmutableArrayPtr raw(const Array& array) {
    return static_cast<ImmutableArrayPtr>(array.ptr());
  }

  friend class Class;
};

class GrowableObjectArray : public Instance {
 public:
  intptr_t Capacity() const {
    NoSafepointScope no_safepoint;
    ASSERT(!IsNull());
    return Smi::Value(DataArray()->length());
  }
  intptr_t Length() const {
    ASSERT(!IsNull());
    return Smi::Value(untag()->length());
  }
  void SetLength(intptr_t value) const {
    // This is only safe because we create a new Smi, which does not cause
    // heap allocation.
    untag()->set_length(Smi::New(value));
  }

  ArrayPtr data() const { return untag()->data(); }
  void SetData(const Array& value) const { untag()->set_data(value.ptr()); }

  ObjectPtr At(intptr_t index) const {
    NoSafepointScope no_safepoint;
    ASSERT(!IsNull());
    ASSERT(index < Length());
    return data()->untag()->element(index);
  }
  void SetAt(intptr_t index, const Object& value) const {
    ASSERT(!IsNull());
    ASSERT(index < Length());

    // TODO(iposva): Add storing NoSafepointScope.
    data()->untag()->set_element(index, value.ptr());
  }

  void Add(const Object& value, Heap::Space space = Heap::kNew) const;

  void Grow(intptr_t new_capacity, Heap::Space space = Heap::kNew) const;
  ObjectPtr RemoveLast() const;

  virtual TypeArgumentsPtr GetTypeArguments() const {
    return untag()->type_arguments();
  }
  virtual void SetTypeArguments(const TypeArguments& value) const {
    // A GrowableObjectArray is raw or takes one type argument. However, its
    // type argument vector may be longer than 1 due to a type optimization
    // reusing the type argument vector of the instantiator.
    ASSERT(value.IsNull() || ((value.Length() >= 1) && value.IsInstantiated() &&
                              value.IsCanonical()));

    untag()->set_type_arguments(value.ptr());
  }

  // We don't expect a growable object array to be canonicalized.
  virtual bool CanonicalizeEquals(const Instance& other) const {
    UNREACHABLE();
    return false;
  }

  // We don't expect a growable object array to be canonicalized.
  virtual InstancePtr CanonicalizeLocked(Thread* thread) const {
    UNREACHABLE();
    return Instance::null();
  }

  static intptr_t type_arguments_offset() {
    return OFFSET_OF(UntaggedGrowableObjectArray, type_arguments_);
  }

  static intptr_t length_offset() {
    return OFFSET_OF(UntaggedGrowableObjectArray, length_);
  }
  static intptr_t data_offset() {
    return OFFSET_OF(UntaggedGrowableObjectArray, data_);
  }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedGrowableObjectArray));
  }

  static GrowableObjectArrayPtr New(Heap::Space space = Heap::kNew) {
    return New(kDefaultInitialCapacity, space);
  }
  static GrowableObjectArrayPtr New(intptr_t capacity,
                                    Heap::Space space = Heap::kNew);
  static GrowableObjectArrayPtr New(const Array& array,
                                    Heap::Space space = Heap::kNew);

  static SmiPtr NoSafepointLength(const GrowableObjectArrayPtr array) {
    return array->untag()->length();
  }

  static ArrayPtr NoSafepointData(const GrowableObjectArrayPtr array) {
    return array->untag()->data();
  }

 private:
  UntaggedArray* DataArray() const { return data()->untag(); }

  static const int kDefaultInitialCapacity = 0;

  FINAL_HEAP_OBJECT_IMPLEMENTATION(GrowableObjectArray, Instance);
  friend class Array;
  friend class Class;
};

class Float32x4 : public Instance {
 public:
  static Float32x4Ptr New(float value0,
                          float value1,
                          float value2,
                          float value3,
                          Heap::Space space = Heap::kNew);
  static Float32x4Ptr New(simd128_value_t value,
                          Heap::Space space = Heap::kNew);

  float x() const;
  float y() const;
  float z() const;
  float w() const;

  void set_x(float x) const;
  void set_y(float y) const;
  void set_z(float z) const;
  void set_w(float w) const;

  simd128_value_t value() const;
  void set_value(simd128_value_t value) const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedFloat32x4));
  }

  static intptr_t value_offset() {
    return OFFSET_OF(UntaggedFloat32x4, value_);
  }

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(Float32x4, Instance);
  friend class Class;
};

class Int32x4 : public Instance {
 public:
  static Int32x4Ptr New(int32_t value0,
                        int32_t value1,
                        int32_t value2,
                        int32_t value3,
                        Heap::Space space = Heap::kNew);
  static Int32x4Ptr New(simd128_value_t value, Heap::Space space = Heap::kNew);

  int32_t x() const;
  int32_t y() const;
  int32_t z() const;
  int32_t w() const;

  void set_x(int32_t x) const;
  void set_y(int32_t y) const;
  void set_z(int32_t z) const;
  void set_w(int32_t w) const;

  simd128_value_t value() const;
  void set_value(simd128_value_t value) const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedInt32x4));
  }

  static intptr_t value_offset() { return OFFSET_OF(UntaggedInt32x4, value_); }

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(Int32x4, Instance);
  friend class Class;
};

class Float64x2 : public Instance {
 public:
  static Float64x2Ptr New(double value0,
                          double value1,
                          Heap::Space space = Heap::kNew);
  static Float64x2Ptr New(simd128_value_t value,
                          Heap::Space space = Heap::kNew);

  double x() const;
  double y() const;

  void set_x(double x) const;
  void set_y(double y) const;

  simd128_value_t value() const;
  void set_value(simd128_value_t value) const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedFloat64x2));
  }

  static intptr_t value_offset() {
    return OFFSET_OF(UntaggedFloat64x2, value_);
  }

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(Float64x2, Instance);
  friend class Class;
};

class PointerBase : public Instance {
 public:
  static intptr_t data_offset() {
    return OFFSET_OF(UntaggedPointerBase, data_);
  }
};

class TypedDataBase : public PointerBase {
 public:
  static intptr_t length_offset() {
    return OFFSET_OF(UntaggedTypedDataBase, length_);
  }

  SmiPtr length() const { return untag()->length(); }

  intptr_t Length() const {
    ASSERT(!IsNull());
    return Smi::Value(untag()->length());
  }

  intptr_t LengthInBytes() const {
    return ElementSizeInBytes(ptr()->GetClassId()) * Length();
  }

  TypedDataElementType ElementType() const {
    return ElementType(ptr()->GetClassId());
  }

  intptr_t ElementSizeInBytes() const {
    return element_size(ElementType(ptr()->GetClassId()));
  }

  static intptr_t ElementSizeInBytes(classid_t cid) {
    return element_size(ElementType(cid));
  }

  static TypedDataElementType ElementType(classid_t cid) {
    if (cid == kByteDataViewCid) {
      return kUint8ArrayElement;
    } else if (IsTypedDataClassId(cid)) {
      const intptr_t index =
          (cid - kTypedDataInt8ArrayCid - kTypedDataCidRemainderInternal) / 3;
      return static_cast<TypedDataElementType>(index);
    } else if (IsTypedDataViewClassId(cid)) {
      const intptr_t index =
          (cid - kTypedDataInt8ArrayCid - kTypedDataCidRemainderView) / 3;
      return static_cast<TypedDataElementType>(index);
    } else {
      ASSERT(IsExternalTypedDataClassId(cid));
      const intptr_t index =
          (cid - kTypedDataInt8ArrayCid - kTypedDataCidRemainderExternal) / 3;
      return static_cast<TypedDataElementType>(index);
    }
  }

  void* DataAddr(intptr_t byte_offset) const {
    ASSERT((byte_offset == 0) ||
           ((byte_offset > 0) && (byte_offset < LengthInBytes())));
    return reinterpret_cast<void*>(Validate(untag()->data_) + byte_offset);
  }

#define TYPED_GETTER_SETTER(name, type)                                        \
  type Get##name(intptr_t byte_offset) const {                                 \
    NoSafepointScope no_safepoint;                                             \
    return LoadUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset)));      \
  }                                                                            \
  void Set##name(intptr_t byte_offset, type value) const {                     \
    NoSafepointScope no_safepoint;                                             \
    StoreUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset)), value);     \
  }

  TYPED_GETTER_SETTER(Int8, int8_t)
  TYPED_GETTER_SETTER(Uint8, uint8_t)
  TYPED_GETTER_SETTER(Int16, int16_t)
  TYPED_GETTER_SETTER(Uint16, uint16_t)
  TYPED_GETTER_SETTER(Int32, int32_t)
  TYPED_GETTER_SETTER(Uint32, uint32_t)
  TYPED_GETTER_SETTER(Int64, int64_t)
  TYPED_GETTER_SETTER(Uint64, uint64_t)
  TYPED_GETTER_SETTER(Float32, float)
  TYPED_GETTER_SETTER(Float64, double)
  TYPED_GETTER_SETTER(Float32x4, simd128_value_t)
  TYPED_GETTER_SETTER(Int32x4, simd128_value_t)
  TYPED_GETTER_SETTER(Float64x2, simd128_value_t)

#undef TYPED_GETTER_SETTER

 protected:
  void SetLength(intptr_t value) const {
    ASSERT(value <= Smi::kMaxValue);
    untag()->set_length(Smi::New(value));
  }

  virtual uint8_t* Validate(uint8_t* data) const {
    return UnsafeMutableNonPointer(data);
  }

 private:
  friend class Class;

  static intptr_t element_size(intptr_t index) {
    ASSERT(0 <= index && index < kNumElementSizes);
    intptr_t size = element_size_table[index];
    ASSERT(size != 0);
    return size;
  }
  static const intptr_t kNumElementSizes =
      (kTypedDataFloat64x2ArrayCid - kTypedDataInt8ArrayCid) / 3 + 1;
  static const intptr_t element_size_table[kNumElementSizes];

  HEAP_OBJECT_IMPLEMENTATION(TypedDataBase, PointerBase);
};

class TypedData : public TypedDataBase {
 public:
  virtual bool CanonicalizeEquals(const Instance& other) const;
  virtual uint32_t CanonicalizeHash() const;

#define TYPED_GETTER_SETTER(name, type)                                        \
  type Get##name(intptr_t byte_offset) const {                                 \
    ASSERT((byte_offset >= 0) &&                                               \
           (byte_offset + static_cast<intptr_t>(sizeof(type)) - 1) <           \
               LengthInBytes());                                               \
    return LoadUnaligned(ReadOnlyDataAddr<type>(byte_offset));                 \
  }                                                                            \
  void Set##name(intptr_t byte_offset, type value) const {                     \
    NoSafepointScope no_safepoint;                                             \
    StoreUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset)), value);     \
  }

  TYPED_GETTER_SETTER(Int8, int8_t)
  TYPED_GETTER_SETTER(Uint8, uint8_t)
  TYPED_GETTER_SETTER(Int16, int16_t)
  TYPED_GETTER_SETTER(Uint16, uint16_t)
  TYPED_GETTER_SETTER(Int32, int32_t)
  TYPED_GETTER_SETTER(Uint32, uint32_t)
  TYPED_GETTER_SETTER(Int64, int64_t)
  TYPED_GETTER_SETTER(Uint64, uint64_t)
  TYPED_GETTER_SETTER(Float32, float)
  TYPED_GETTER_SETTER(Float64, double)
  TYPED_GETTER_SETTER(Float32x4, simd128_value_t)
  TYPED_GETTER_SETTER(Int32x4, simd128_value_t)
  TYPED_GETTER_SETTER(Float64x2, simd128_value_t)

#undef TYPED_GETTER_SETTER

  static intptr_t payload_offset() {
    return UntaggedTypedData::payload_offset();
  }

  static intptr_t InstanceSize() {
    ASSERT(sizeof(UntaggedTypedData) ==
           OFFSET_OF_RETURNED_VALUE(UntaggedTypedData, internal_data));
    return 0;
  }

  static intptr_t InstanceSize(intptr_t lengthInBytes) {
    ASSERT(0 <= lengthInBytes && lengthInBytes <= kSmiMax);
    return RoundedAllocationSize(sizeof(UntaggedTypedData) + lengthInBytes);
  }

  static intptr_t MaxElements(intptr_t class_id) {
    ASSERT(IsTypedDataClassId(class_id));
    return (kSmiMax / ElementSizeInBytes(class_id));
  }

  static intptr_t MaxNewSpaceElements(intptr_t class_id) {
    ASSERT(IsTypedDataClassId(class_id));
    return (Heap::kNewAllocatableSize - sizeof(UntaggedTypedData)) /
           ElementSizeInBytes(class_id);
  }

  static TypedDataPtr New(intptr_t class_id,
                          intptr_t len,
                          Heap::Space space = Heap::kNew);

  static void Copy(const TypedDataBase& dst,
                   intptr_t dst_offset_in_bytes,
                   const TypedDataBase& src,
                   intptr_t src_offset_in_bytes,
                   intptr_t length_in_bytes) {
    ASSERT(Utils::RangeCheck(src_offset_in_bytes, length_in_bytes,
                             src.LengthInBytes()));
    ASSERT(Utils::RangeCheck(dst_offset_in_bytes, length_in_bytes,
                             dst.LengthInBytes()));
    {
      NoSafepointScope no_safepoint;
      if (length_in_bytes > 0) {
        memmove(dst.DataAddr(dst_offset_in_bytes),
                src.DataAddr(src_offset_in_bytes), length_in_bytes);
      }
    }
  }

  static void ClampedCopy(const TypedDataBase& dst,
                          intptr_t dst_offset_in_bytes,
                          const TypedDataBase& src,
                          intptr_t src_offset_in_bytes,
                          intptr_t length_in_bytes) {
    ASSERT(Utils::RangeCheck(src_offset_in_bytes, length_in_bytes,
                             src.LengthInBytes()));
    ASSERT(Utils::RangeCheck(dst_offset_in_bytes, length_in_bytes,
                             dst.LengthInBytes()));
    {
      NoSafepointScope no_safepoint;
      if (length_in_bytes > 0) {
        uint8_t* dst_data =
            reinterpret_cast<uint8_t*>(dst.DataAddr(dst_offset_in_bytes));
        int8_t* src_data =
            reinterpret_cast<int8_t*>(src.DataAddr(src_offset_in_bytes));
        for (intptr_t ix = 0; ix < length_in_bytes; ix++) {
          int8_t v = *src_data;
          if (v < 0) v = 0;
          *dst_data = v;
          src_data++;
          dst_data++;
        }
      }
    }
  }

  static bool IsTypedData(const Instance& obj) {
    ASSERT(!obj.IsNull());
    intptr_t cid = obj.ptr()->GetClassId();
    return IsTypedDataClassId(cid);
  }

 protected:
  void RecomputeDataField() { ptr()->untag()->RecomputeDataField(); }

 private:
  // Provides const access to non-pointer, non-aligned data within the object.
  // Such access does not need a write barrier, but it is *not* GC-safe, since
  // the object might move.
  //
  // Therefore this method is private and the call-sites in this class need to
  // ensure the returned pointer does not escape.
  template <typename FieldType>
  const FieldType* ReadOnlyDataAddr(intptr_t byte_offset) const {
    return reinterpret_cast<const FieldType*>((untag()->data()) + byte_offset);
  }

  FINAL_HEAP_OBJECT_IMPLEMENTATION(TypedData, TypedDataBase);
  friend class Class;
  friend class ExternalTypedData;
  friend class TypedDataView;
};

class ExternalTypedData : public TypedDataBase {
 public:
  // Alignment of data when serializing ExternalTypedData in a clustered
  // snapshot. Should be independent of word size.
  static const int kDataSerializationAlignment = 8;

  FinalizablePersistentHandle* AddFinalizer(void* peer,
                                            Dart_HandleFinalizer callback,
                                            intptr_t external_size) const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedExternalTypedData));
  }

  static intptr_t MaxElements(intptr_t class_id) {
    ASSERT(IsExternalTypedDataClassId(class_id));
    return (kSmiMax / ElementSizeInBytes(class_id));
  }

  static ExternalTypedDataPtr New(
      intptr_t class_id,
      uint8_t* data,
      intptr_t len,
      Heap::Space space = Heap::kNew,
      bool perform_eager_msan_initialization_check = true);

  static ExternalTypedDataPtr NewFinalizeWithFree(uint8_t* data, intptr_t len);

  static bool IsExternalTypedData(const Instance& obj) {
    ASSERT(!obj.IsNull());
    intptr_t cid = obj.ptr()->GetClassId();
    return IsExternalTypedDataClassId(cid);
  }

 protected:
  virtual uint8_t* Validate(uint8_t* data) const { return data; }

  void SetLength(intptr_t value) const {
    ASSERT(value <= Smi::kMaxValue);
    untag()->set_length(Smi::New(value));
  }

  void SetData(uint8_t* data) const {
    ASSERT(!IsolateGroup::Current()->heap()->Contains(
        reinterpret_cast<uword>(data)));
    StoreNonPointer(&untag()->data_, data);
  }

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(ExternalTypedData, TypedDataBase);
  friend class Class;
};

class TypedDataView : public TypedDataBase {
 public:
  static TypedDataViewPtr New(intptr_t class_id,
                              Heap::Space space = Heap::kNew);
  static TypedDataViewPtr New(intptr_t class_id,
                              const TypedDataBase& typed_data,
                              intptr_t offset_in_bytes,
                              intptr_t length,
                              Heap::Space space = Heap::kNew);

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedTypedDataView));
  }

  static InstancePtr Data(const TypedDataView& view) {
    return view.typed_data();
  }

  static SmiPtr OffsetInBytes(const TypedDataView& view) {
    return view.offset_in_bytes();
  }

  static bool IsExternalTypedDataView(const TypedDataView& view_obj) {
    const auto& data = Instance::Handle(Data(view_obj));
    intptr_t cid = data.ptr()->GetClassId();
    ASSERT(IsTypedDataClassId(cid) || IsExternalTypedDataClassId(cid));
    return IsExternalTypedDataClassId(cid);
  }

  static intptr_t typed_data_offset() {
    return OFFSET_OF(UntaggedTypedDataView, typed_data_);
  }

  static intptr_t offset_in_bytes_offset() {
    return OFFSET_OF(UntaggedTypedDataView, offset_in_bytes_);
  }

  InstancePtr typed_data() const { return untag()->typed_data(); }

  void InitializeWith(const TypedDataBase& typed_data,
                      intptr_t offset_in_bytes,
                      intptr_t length) {
    const classid_t cid = typed_data.GetClassId();
    ASSERT(IsTypedDataClassId(cid) || IsExternalTypedDataClassId(cid));
    untag()->set_typed_data(typed_data.ptr());
    untag()->set_length(Smi::New(length));
    untag()->set_offset_in_bytes(Smi::New(offset_in_bytes));

    // Update the inner pointer.
    RecomputeDataField();
  }

  SmiPtr offset_in_bytes() const { return untag()->offset_in_bytes(); }

 protected:
  virtual uint8_t* Validate(uint8_t* data) const { return data; }

 private:
  void RecomputeDataField() { ptr()->untag()->RecomputeDataField(); }

  void Clear() {
    untag()->set_length(Smi::New(0));
    untag()->set_offset_in_bytes(Smi::New(0));
    StoreNonPointer(&untag()->data_, nullptr);
    untag()->set_typed_data(TypedDataBase::RawCast(Object::null()));
  }

  FINAL_HEAP_OBJECT_IMPLEMENTATION(TypedDataView, TypedDataBase);
  friend class Class;
  friend class Object;
  friend class TypedDataViewDeserializationCluster;
};

class ByteBuffer : public AllStatic {
 public:
  static constexpr bool ContainsCompressedPointers() {
    return Instance::ContainsCompressedPointers();
  }

  static InstancePtr Data(const Instance& view_obj) {
    ASSERT(!view_obj.IsNull());
    return reinterpret_cast<CompressedInstancePtr*>(
               reinterpret_cast<uword>(view_obj.untag()) + data_offset())
        ->Decompress(view_obj.untag()->heap_base());
  }

  static intptr_t NumberOfFields() { return kNumFields; }

  static intptr_t data_offset() {
    return sizeof(UntaggedObject) + (kCompressedWordSize * kDataIndex);
  }

 private:
  enum {
    kDataIndex = 0,
    kNumFields = 1,
  };
};

class Pointer : public Instance {
 public:
  static PointerPtr New(const AbstractType& type_arg,
                        uword native_address,
                        Heap::Space space = Heap::kNew);

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedPointer));
  }

  static bool IsPointer(const Instance& obj);

  size_t NativeAddress() const {
    return reinterpret_cast<size_t>(untag()->data_);
  }

  void SetNativeAddress(size_t address) const {
    uint8_t* value = reinterpret_cast<uint8_t*>(address);
    StoreNonPointer(&untag()->data_, value);
  }

  static intptr_t type_arguments_offset() {
    return OFFSET_OF(UntaggedPointer, type_arguments_);
  }

  static const intptr_t kNativeTypeArgPos = 0;

  // Fetches the NativeType type argument.
  AbstractTypePtr type_argument() const {
    TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
    return type_args.TypeAtNullSafe(Pointer::kNativeTypeArgPos);
  }

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(Pointer, Instance);

  friend class Class;
};

class DynamicLibrary : public Instance {
 public:
  static DynamicLibraryPtr New(void* handle, Heap::Space space = Heap::kNew);

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedDynamicLibrary));
  }

  static bool IsDynamicLibrary(const Instance& obj) {
    ASSERT(!obj.IsNull());
    intptr_t cid = obj.ptr()->GetClassId();
    return IsFfiDynamicLibraryClassId(cid);
  }

  void* GetHandle() const {
    ASSERT(!IsNull());
    return untag()->handle_;
  }

  void SetHandle(void* value) const {
    StoreNonPointer(&untag()->handle_, value);
  }

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(DynamicLibrary, Instance);

  friend class Class;
};

class LinkedHashBase : public Instance {
 public:
  // Keep consistent with _indexSizeToHashMask in compact_hash.dart.
  static intptr_t IndexSizeToHashMask(intptr_t index_size) {
    ASSERT(index_size >= kInitialIndexSize);
    intptr_t index_bits = Utils::BitLength(index_size) - 2;
#if defined(HAS_SMI_63_BITS)
    return (1 << (32 - index_bits)) - 1;
#else
    return (1 << (Object::kHashBits - index_bits)) - 1;
#endif
  }
  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedLinkedHashBase));
  }

  static intptr_t type_arguments_offset() {
    return OFFSET_OF(UntaggedLinkedHashBase, type_arguments_);
  }

  static intptr_t index_offset() {
    return OFFSET_OF(UntaggedLinkedHashBase, index_);
  }

  static intptr_t data_offset() {
    return OFFSET_OF(UntaggedLinkedHashBase, data_);
  }

  static intptr_t hash_mask_offset() {
    return OFFSET_OF(UntaggedLinkedHashBase, hash_mask_);
  }

  static intptr_t used_data_offset() {
    return OFFSET_OF(UntaggedLinkedHashBase, used_data_);
  }

  static intptr_t deleted_keys_offset() {
    return OFFSET_OF(UntaggedLinkedHashBase, deleted_keys_);
  }

  static const LinkedHashBase& Cast(const Object& obj) {
    ASSERT(obj.IsLinkedHashMap() || obj.IsLinkedHashSet());
    return static_cast<const LinkedHashBase&>(obj);
  }

  bool IsImmutable() const {
    return GetClassId() == kImmutableLinkedHashMapCid ||
           GetClassId() == kImmutableLinkedHashSetCid;
  }

  virtual TypeArgumentsPtr GetTypeArguments() const {
    return untag()->type_arguments();
  }
  virtual void SetTypeArguments(const TypeArguments& value) const {
    const intptr_t num_type_args = IsLinkedHashMap() ? 2 : 1;
    ASSERT(value.IsNull() ||
           ((value.Length() >= num_type_args) &&
            value.IsInstantiated() /*&& value.IsCanonical()*/));
    // TODO(asiva): Values read from a message snapshot are not properly marked
    // as canonical. See for example tests/isolate/message3_test.dart.
    untag()->set_type_arguments(value.ptr());
  }

  TypedDataPtr index() const { return untag()->index(); }
  void set_index(const TypedData& value) const {
    ASSERT(!value.IsNull());
    untag()->set_index(value.ptr());
  }

  ArrayPtr data() const { return untag()->data(); }
  void set_data(const Array& value) const { untag()->set_data(value.ptr()); }

  SmiPtr hash_mask() const { return untag()->hash_mask(); }
  void set_hash_mask(intptr_t value) const {
    untag()->set_hash_mask(Smi::New(value));
  }

  SmiPtr used_data() const { return untag()->used_data(); }
  void set_used_data(intptr_t value) const {
    untag()->set_used_data(Smi::New(value));
  }

  SmiPtr deleted_keys() const { return untag()->deleted_keys(); }
  void set_deleted_keys(intptr_t value) const {
    untag()->set_deleted_keys(Smi::New(value));
  }

  intptr_t Length() const {
    // The map or set may be uninitialized.
    if (untag()->used_data() == Object::null()) return 0;
    if (untag()->deleted_keys() == Object::null()) return 0;

    intptr_t used = Smi::Value(untag()->used_data());
    if (IsLinkedHashMap()) {
      used >>= 1;
    }
    const intptr_t deleted = Smi::Value(untag()->deleted_keys());
    return used - deleted;
  }

  // We do not compute the indices in the VM, but we do precompute the hash
  // mask to avoid a load acquire barrier on reading the combination of index
  // and hash mask.
  void ComputeAndSetHashMask() const;

  virtual bool CanonicalizeEquals(const Instance& other) const;
  virtual uint32_t CanonicalizeHash() const;
  virtual void CanonicalizeFieldsLocked(Thread* thread) const;

 protected:
  // Keep this in sync with Dart implementation (lib/compact_hash.dart).
  static const intptr_t kInitialIndexBits = 2;
  static const intptr_t kInitialIndexSize = 1 << (kInitialIndexBits + 1);

 private:
  LinkedHashBasePtr ptr() const { return static_cast<LinkedHashBasePtr>(ptr_); }
  UntaggedLinkedHashBase* untag() const {
    ASSERT(ptr() != null());
    return const_cast<UntaggedLinkedHashBase*>(ptr()->untag());
  }

  friend class Class;
  friend class ImmutableLinkedHashBase;
  friend class LinkedHashBaseDeserializationCluster;
};

class ImmutableLinkedHashBase : public AllStatic {
 public:
  static constexpr bool ContainsCompressedPointers() {
    return LinkedHashBase::ContainsCompressedPointers();
  }

  static intptr_t data_offset() { return LinkedHashBase::data_offset(); }
};

// Corresponds to
// - "new Map()",
// - non-const map literals, and
// - the default constructor of LinkedHashMap in dart:collection.
class LinkedHashMap : public LinkedHashBase {
 public:
  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedLinkedHashMap));
  }

  // Allocates a map with some default capacity, just like "new Map()".
  static LinkedHashMapPtr NewDefault(intptr_t class_id = kLinkedHashMapCid,
                                     Heap::Space space = Heap::kNew);
  static LinkedHashMapPtr 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 = Heap::kNew);

  // This iterator differs somewhat from its Dart counterpart (_CompactIterator
  // in runtime/lib/compact_hash.dart):
  //  - There are no checks for concurrent modifications.
  //  - Accessing a key or value before the first call to MoveNext and after
  //    MoveNext returns false will result in crashes.
  class Iterator : public ValueObject {
   public:
    explicit Iterator(const LinkedHashMap& map)
        : data_(Array::Handle(map.data())),
          scratch_(Object::Handle()),
          offset_(-2),
          length_(Smi::Value(map.used_data())) {}

    bool MoveNext() {
      while (true) {
        offset_ += 2;
        if (offset_ >= length_) {
          return false;
        }
        scratch_ = data_.At(offset_);
        if (scratch_.ptr() != data_.ptr()) {
          // Slot is not deleted (self-reference indicates deletion).
          return true;
        }
      }
    }

    ObjectPtr CurrentKey() const { return data_.At(offset_); }

    ObjectPtr CurrentValue() const { return data_.At(offset_ + 1); }

   private:
    const Array& data_;
    Object& scratch_;
    intptr_t offset_;
    const intptr_t length_;
  };

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(LinkedHashMap, LinkedHashBase);

  // Allocate a map, but leave all fields set to null.
  // Used during deserialization (since map might contain itself as key/value).
  static LinkedHashMapPtr NewUninitialized(intptr_t class_id,
                                           Heap::Space space = Heap::kNew);

  friend class Class;
  friend class ImmutableLinkedHashMap;
  friend class LinkedHashMapDeserializationCluster;
};

class ImmutableLinkedHashMap : public AllStatic {
 public:
  static constexpr bool ContainsCompressedPointers() {
    return LinkedHashMap::ContainsCompressedPointers();
  }

  static ImmutableLinkedHashMapPtr NewDefault(Heap::Space space = Heap::kNew);

  static ImmutableLinkedHashMapPtr NewUninitialized(
      Heap::Space space = Heap::kNew);

  static const ClassId kClassId = kImmutableLinkedHashMapCid;

  static intptr_t InstanceSize() { return LinkedHashMap::InstanceSize(); }

 private:
  static intptr_t NextFieldOffset() {
    // Indicates this class cannot be extended by dart code.
    return -kWordSize;
  }

  static ImmutableLinkedHashMapPtr raw(const LinkedHashMap& map) {
    return static_cast<ImmutableLinkedHashMapPtr>(map.ptr());
  }

  friend class Class;
};

class LinkedHashSet : public LinkedHashBase {
 public:
  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedLinkedHashSet));
  }

  // Allocates a set with some default capacity, just like "new Set()".
  static LinkedHashSetPtr NewDefault(intptr_t class_id = kLinkedHashSetCid,
                                     Heap::Space space = Heap::kNew);
  static LinkedHashSetPtr 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 = Heap::kNew);

  // This iterator differs somewhat from its Dart counterpart (_CompactIterator
  // in runtime/lib/compact_hash.dart):
  //  - There are no checks for concurrent modifications.
  //  - Accessing a key or value before the first call to MoveNext and after
  //    MoveNext returns false will result in crashes.
  class Iterator : public ValueObject {
   public:
    explicit Iterator(const LinkedHashSet& set)
        : data_(Array::Handle(set.data())),
          scratch_(Object::Handle()),
          offset_(-1),
          length_(Smi::Value(set.used_data())) {}

    bool MoveNext() {
      while (true) {
        offset_++;
        if (offset_ >= length_) {
          return false;
        }
        scratch_ = data_.At(offset_);
        if (scratch_.ptr() != data_.ptr()) {
          // Slot is not deleted (self-reference indicates deletion).
          return true;
        }
      }
    }

    ObjectPtr CurrentKey() const { return data_.At(offset_); }

   private:
    const Array& data_;
    Object& scratch_;
    intptr_t offset_;
    const intptr_t length_;
  };

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(LinkedHashSet, LinkedHashBase);

  // Allocate a set, but leave all fields set to null.
  // Used during deserialization (since set might contain itself as key/value).
  static LinkedHashSetPtr NewUninitialized(intptr_t class_id,
                                           Heap::Space space = Heap::kNew);

  friend class Class;
  friend class ImmutableLinkedHashSet;
  friend class LinkedHashSetDeserializationCluster;
};

class ImmutableLinkedHashSet : public AllStatic {
 public:
  static constexpr bool ContainsCompressedPointers() {
    return LinkedHashSet::ContainsCompressedPointers();
  }

  static ImmutableLinkedHashSetPtr NewDefault(Heap::Space space = Heap::kNew);

  static ImmutableLinkedHashSetPtr NewUninitialized(
      Heap::Space space = Heap::kNew);

  static const ClassId kClassId = kImmutableLinkedHashSetCid;

  static intptr_t InstanceSize() { return LinkedHashSet::InstanceSize(); }

 private:
  static intptr_t NextFieldOffset() {
    // Indicates this class cannot be extended by dart code.
    return -kWordSize;
  }

  static ImmutableLinkedHashSetPtr raw(const LinkedHashSet& map) {
    return static_cast<ImmutableLinkedHashSetPtr>(map.ptr());
  }

  friend class Class;
};

class Closure : public Instance {
 public:
#if defined(DART_PRECOMPILED_RUNTIME)
  uword entry_point() const { return untag()->entry_point_; }
  void set_entry_point(uword entry_point) const {
    StoreNonPointer(&untag()->entry_point_, entry_point);
  }
  static intptr_t entry_point_offset() {
    return OFFSET_OF(UntaggedClosure, entry_point_);
  }
#endif

  TypeArgumentsPtr instantiator_type_arguments() const {
    return untag()->instantiator_type_arguments();
  }
  void set_instantiator_type_arguments(const TypeArguments& args) const {
    untag()->set_instantiator_type_arguments(args.ptr());
  }
  static intptr_t instantiator_type_arguments_offset() {
    return OFFSET_OF(UntaggedClosure, instantiator_type_arguments_);
  }

  TypeArgumentsPtr function_type_arguments() const {
    return untag()->function_type_arguments();
  }
  void set_function_type_arguments(const TypeArguments& args) const {
    untag()->set_function_type_arguments(args.ptr());
  }
  static intptr_t function_type_arguments_offset() {
    return OFFSET_OF(UntaggedClosure, function_type_arguments_);
  }

  TypeArgumentsPtr delayed_type_arguments() const {
    return untag()->delayed_type_arguments();
  }
  void set_delayed_type_arguments(const TypeArguments& args) const {
    untag()->set_delayed_type_arguments(args.ptr());
  }
  static intptr_t delayed_type_arguments_offset() {
    return OFFSET_OF(UntaggedClosure, delayed_type_arguments_);
  }

  FunctionPtr function() const { return untag()->function(); }
  static intptr_t function_offset() {
    return OFFSET_OF(UntaggedClosure, function_);
  }
  static FunctionPtr FunctionOf(ClosurePtr closure) {
    return closure.untag()->function();
  }

  ContextPtr context() const { return untag()->context(); }
  static intptr_t context_offset() {
    return OFFSET_OF(UntaggedClosure, context_);
  }
  static ContextPtr ContextOf(ClosurePtr closure) {
    return closure.untag()->context();
  }

  // Returns whether the closure is generic, that is, it has a generic closure
  // function and no delayed type arguments.
  bool IsGeneric() const {
    return delayed_type_arguments() == Object::empty_type_arguments().ptr();
  }

  SmiPtr hash() const { return untag()->hash(); }
  static intptr_t hash_offset() { return OFFSET_OF(UntaggedClosure, hash_); }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedClosure));
  }

  virtual void CanonicalizeFieldsLocked(Thread* thread) const;
  virtual bool CanonicalizeEquals(const Instance& other) const;
  virtual uint32_t CanonicalizeHash() const {
    return Function::Handle(function()).Hash();
  }
  uword ComputeHash() const;

  static ClosurePtr New(const TypeArguments& instantiator_type_arguments,
                        const TypeArguments& function_type_arguments,
                        const Function& function,
                        const Context& context,
                        Heap::Space space = Heap::kNew);

  static ClosurePtr New(const TypeArguments& instantiator_type_arguments,
                        const TypeArguments& function_type_arguments,
                        const TypeArguments& delayed_type_arguments,
                        const Function& function,
                        const Context& context,
                        Heap::Space space = Heap::kNew);

  FunctionTypePtr GetInstantiatedSignature(Zone* zone) const;

 private:
  static ClosurePtr New();

  FINAL_HEAP_OBJECT_IMPLEMENTATION(Closure, Instance);
  friend class Class;
};

class Capability : public Instance {
 public:
  uint64_t Id() const { return untag()->id_; }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedCapability));
  }
  static CapabilityPtr New(uint64_t id, Heap::Space space = Heap::kNew);

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(Capability, Instance);
  friend class Class;
};

class ReceivePort : public Instance {
 public:
  SendPortPtr send_port() const { return untag()->send_port(); }
  Dart_Port Id() const { return send_port()->untag()->id_; }

  InstancePtr handler() const { return untag()->handler(); }
  void set_handler(const Instance& value) const;

#if !defined(PRODUCT)
  StackTracePtr allocation_location() const {
    return untag()->allocation_location();
  }

  StringPtr debug_name() const { return untag()->debug_name(); }
#endif

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedReceivePort));
  }
  static ReceivePortPtr New(Dart_Port id,
                            const String& debug_name,
                            bool is_control_port,
                            Heap::Space space = Heap::kNew);

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(ReceivePort, Instance);
  friend class Class;
};

class SendPort : public Instance {
 public:
  Dart_Port Id() const { return untag()->id_; }

  Dart_Port origin_id() const { return untag()->origin_id_; }
  void set_origin_id(Dart_Port id) const {
    ASSERT(origin_id() == 0);
    StoreNonPointer(&(untag()->origin_id_), id);
  }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedSendPort));
  }
  static SendPortPtr New(Dart_Port id, Heap::Space space = Heap::kNew);
  static SendPortPtr New(Dart_Port id,
                         Dart_Port origin_id,
                         Heap::Space space = Heap::kNew);

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(SendPort, Instance);
  friend class Class;
};

// This is allocated when new instance of TransferableTypedData is created in
// [TransferableTypedData::New].
class TransferableTypedDataPeer {
 public:
  // [data] backing store should be malloc'ed, not new'ed.
  TransferableTypedDataPeer(uint8_t* data, intptr_t length)
      : data_(data), length_(length), handle_(nullptr) {}

  ~TransferableTypedDataPeer() { free(data_); }

  uint8_t* data() const { return data_; }
  intptr_t length() const { return length_; }
  FinalizablePersistentHandle* handle() const { return handle_; }
  void set_handle(FinalizablePersistentHandle* handle) { handle_ = handle; }

  void ClearData() {
    data_ = nullptr;
    length_ = 0;
    handle_ = nullptr;
  }

 private:
  uint8_t* data_;
  intptr_t length_;
  FinalizablePersistentHandle* handle_;

  DISALLOW_COPY_AND_ASSIGN(TransferableTypedDataPeer);
};

class TransferableTypedData : public Instance {
 public:
  static TransferableTypedDataPtr New(uint8_t* data, intptr_t len);

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedTransferableTypedData));
  }

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(TransferableTypedData, Instance);
  friend class Class;
};

class DebuggerStackTrace;

// Internal stacktrace object used in exceptions for printing stack traces.
class StackTrace : public Instance {
 public:
  static const int kPreallocatedStackdepth = 90;

  intptr_t Length() const;

  StackTracePtr async_link() const { return untag()->async_link(); }
  void set_async_link(const StackTrace& async_link) const;
  void set_expand_inlined(bool value) const;

  ArrayPtr code_array() const { return untag()->code_array(); }
  ObjectPtr CodeAtFrame(intptr_t frame_index) const;
  void SetCodeAtFrame(intptr_t frame_index, const Object& code) const;

  TypedDataPtr pc_offset_array() const { return untag()->pc_offset_array(); }
  uword PcOffsetAtFrame(intptr_t frame_index) const;
  void SetPcOffsetAtFrame(intptr_t frame_index, uword pc_offset) const;

  bool skip_sync_start_in_parent_stack() const;
  void set_skip_sync_start_in_parent_stack(bool value) const;

  // The number of frames that should be cut off the top of an async stack trace
  // if it's appended to a synchronous stack trace along a sync-async call.
  //
  // Without cropping, the border would look like:
  //
  // <async function>
  // ---------------------------
  // <asynchronous gap marker>
  // <async function>
  //
  // Since it's not actually an async call, we crop off the last two
  // frames when concatenating the sync and async stacktraces.
  static constexpr intptr_t kSyncAsyncCroppedFrames = 2;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedStackTrace));
  }
  static StackTracePtr New(const Array& code_array,
                           const TypedData& pc_offset_array,
                           Heap::Space space = Heap::kNew);

  static StackTracePtr New(const Array& code_array,
                           const TypedData& pc_offset_array,
                           const StackTrace& async_link,
                           bool skip_sync_start_in_parent_stack,
                           Heap::Space space = Heap::kNew);

 private:
  void set_code_array(const Array& code_array) const;
  void set_pc_offset_array(const TypedData& pc_offset_array) const;
  bool expand_inlined() const;

  FINAL_HEAP_OBJECT_IMPLEMENTATION(StackTrace, Instance);
  friend class Class;
  friend class DebuggerStackTrace;
};

class RegExpFlags {
 public:
  // Flags are passed to a regex object as follows:
  // 'i': ignore case, 'g': do global matches, 'm': pattern is multi line,
  // 'u': pattern is full Unicode, not just BMP, 's': '.' in pattern matches
  // all characters including line terminators.
  enum Flags {
    kNone = 0,
    kGlobal = 1,
    kIgnoreCase = 2,
    kMultiLine = 4,
    kUnicode = 8,
    kDotAll = 16,
  };

  static const int kDefaultFlags = 0;

  RegExpFlags() : value_(kDefaultFlags) {}
  explicit RegExpFlags(int value) : value_(value) {}

  inline bool IsGlobal() const { return (value_ & kGlobal) != 0; }
  inline bool IgnoreCase() const { return (value_ & kIgnoreCase) != 0; }
  inline bool IsMultiLine() const { return (value_ & kMultiLine) != 0; }
  inline bool IsUnicode() const { return (value_ & kUnicode) != 0; }
  inline bool IsDotAll() const { return (value_ & kDotAll) != 0; }

  inline bool NeedsUnicodeCaseEquivalents() {
    // Both unicode and ignore_case flags are set. We need to use ICU to find
    // the closure over case equivalents.
    return IsUnicode() && IgnoreCase();
  }

  void SetGlobal() { value_ |= kGlobal; }
  void SetIgnoreCase() { value_ |= kIgnoreCase; }
  void SetMultiLine() { value_ |= kMultiLine; }
  void SetUnicode() { value_ |= kUnicode; }
  void SetDotAll() { value_ |= kDotAll; }

  const char* ToCString() const;

  int value() const { return value_; }

  bool operator==(const RegExpFlags& other) { return value_ == other.value_; }
  bool operator!=(const RegExpFlags& other) { return value_ != other.value_; }

 private:
  int value_;
};

// Internal JavaScript regular expression object.
class RegExp : public Instance {
 public:
  // Meaning of RegExType:
  // kUninitialized: the type of th regexp has not been initialized yet.
  // kSimple: A simple pattern to match against, using string indexOf operation.
  // kComplex: A complex pattern to match.
  enum RegExType {
    kUninitialized = 0,
    kSimple = 1,
    kComplex = 2,
  };

  enum {
    kTypePos = 0,
    kTypeSize = 2,
    kFlagsPos = 2,
    kFlagsSize = 5,
  };

  class TypeBits : public BitField<int8_t, RegExType, kTypePos, kTypeSize> {};
  class FlagsBits : public BitField<int8_t, intptr_t, kFlagsPos, kFlagsSize> {};

  bool is_initialized() const { return (type() != kUninitialized); }
  bool is_simple() const { return (type() == kSimple); }
  bool is_complex() const { return (type() == kComplex); }

  intptr_t num_registers(bool is_one_byte) const {
    return is_one_byte ? untag()->num_one_byte_registers_
                       : untag()->num_two_byte_registers_;
  }

  StringPtr pattern() const { return untag()->pattern(); }
  intptr_t num_bracket_expressions() const {
    return untag()->num_bracket_expressions_;
  }
  ArrayPtr capture_name_map() const { return untag()->capture_name_map(); }

  TypedDataPtr bytecode(bool is_one_byte, bool sticky) const {
    if (sticky) {
      return TypedData::RawCast(is_one_byte ? untag()->one_byte_sticky()
                                            : untag()->two_byte_sticky());
    } else {
      return TypedData::RawCast(is_one_byte ? untag()->one_byte()
                                            : untag()->two_byte());
    }
  }

  static intptr_t function_offset(intptr_t cid, bool sticky) {
    if (sticky) {
      switch (cid) {
        case kOneByteStringCid:
          return OFFSET_OF(UntaggedRegExp, one_byte_sticky_);
        case kTwoByteStringCid:
          return OFFSET_OF(UntaggedRegExp, two_byte_sticky_);
        case kExternalOneByteStringCid:
          return OFFSET_OF(UntaggedRegExp, external_one_byte_sticky_);
        case kExternalTwoByteStringCid:
          return OFFSET_OF(UntaggedRegExp, external_two_byte_sticky_);
      }
    } else {
      switch (cid) {
        case kOneByteStringCid:
          return OFFSET_OF(UntaggedRegExp, one_byte_);
        case kTwoByteStringCid:
          return OFFSET_OF(UntaggedRegExp, two_byte_);
        case kExternalOneByteStringCid:
          return OFFSET_OF(UntaggedRegExp, external_one_byte_);
        case kExternalTwoByteStringCid:
          return OFFSET_OF(UntaggedRegExp, external_two_byte_);
      }
    }

    UNREACHABLE();
    return -1;
  }

  FunctionPtr function(intptr_t cid, bool sticky) const {
    if (sticky) {
      switch (cid) {
        case kOneByteStringCid:
          return static_cast<FunctionPtr>(untag()->one_byte_sticky());
        case kTwoByteStringCid:
          return static_cast<FunctionPtr>(untag()->two_byte_sticky());
        case kExternalOneByteStringCid:
          return static_cast<FunctionPtr>(untag()->external_one_byte_sticky());
        case kExternalTwoByteStringCid:
          return static_cast<FunctionPtr>(untag()->external_two_byte_sticky());
      }
    } else {
      switch (cid) {
        case kOneByteStringCid:
          return static_cast<FunctionPtr>(untag()->one_byte());
        case kTwoByteStringCid:
          return static_cast<FunctionPtr>(untag()->two_byte());
        case kExternalOneByteStringCid:
          return static_cast<FunctionPtr>(untag()->external_one_byte());
        case kExternalTwoByteStringCid:
          return static_cast<FunctionPtr>(untag()->external_two_byte());
      }
    }

    UNREACHABLE();
    return Function::null();
  }

  void set_pattern(const String& pattern) const;
  void set_function(intptr_t cid, bool sticky, const Function& value) const;
  void set_bytecode(bool is_one_byte,
                    bool sticky,
                    const TypedData& bytecode) const;

  void set_num_bracket_expressions(SmiPtr value) const;
  void set_num_bracket_expressions(const Smi& value) const;
  void set_num_bracket_expressions(intptr_t value) const;
  void set_capture_name_map(const Array& array) const;
  void set_is_global() const {
    RegExpFlags f = flags();
    f.SetGlobal();
    set_flags(f);
  }
  void set_is_ignore_case() const {
    RegExpFlags f = flags();
    f.SetIgnoreCase();
    set_flags(f);
  }
  void set_is_multi_line() const {
    RegExpFlags f = flags();
    f.SetMultiLine();
    set_flags(f);
  }
  void set_is_unicode() const {
    RegExpFlags f = flags();
    f.SetUnicode();
    set_flags(f);
  }
  void set_is_dot_all() const {
    RegExpFlags f = flags();
    f.SetDotAll();
    set_flags(f);
  }
  void set_is_simple() const { set_type(kSimple); }
  void set_is_complex() const { set_type(kComplex); }
  void set_num_registers(bool is_one_byte, intptr_t value) const {
    if (is_one_byte) {
      StoreNonPointer(&untag()->num_one_byte_registers_, value);
    } else {
      StoreNonPointer(&untag()->num_two_byte_registers_, value);
    }
  }

  RegExpFlags flags() const {
    return RegExpFlags(FlagsBits::decode(untag()->type_flags_));
  }
  void set_flags(RegExpFlags flags) const {
    StoreNonPointer(&untag()->type_flags_,
                    FlagsBits::update(flags.value(), untag()->type_flags_));
  }
  const char* Flags() const;

  virtual bool CanonicalizeEquals(const Instance& other) const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedRegExp));
  }

  static RegExpPtr New(Zone* zone, Heap::Space space = Heap::kNew);

 private:
  void set_type(RegExType type) const {
    StoreNonPointer(&untag()->type_flags_,
                    TypeBits::update(type, untag()->type_flags_));
  }

  RegExType type() const { return TypeBits::decode(untag()->type_flags_); }

  FINAL_HEAP_OBJECT_IMPLEMENTATION(RegExp, Instance);
  friend class Class;
};

class WeakProperty : public Instance {
 public:
  ObjectPtr key() const { return untag()->key(); }
  void set_key(const Object& key) const { untag()->set_key(key.ptr()); }
  static intptr_t key_offset() { return OFFSET_OF(UntaggedWeakProperty, key_); }

  ObjectPtr value() const { return untag()->value(); }
  void set_value(const Object& value) const { untag()->set_value(value.ptr()); }
  static intptr_t value_offset() {
    return OFFSET_OF(UntaggedWeakProperty, value_);
  }

  static WeakPropertyPtr New(Heap::Space space = Heap::kNew);

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedWeakProperty));
  }

  static void Clear(WeakPropertyPtr raw_weak) {
    ASSERT(raw_weak->untag()->next_seen_by_gc_ ==
           CompressedWeakPropertyPtr(WeakProperty::null()));
    // This action is performed by the GC. No barrier.
    raw_weak->untag()->key_ = Object::null();
    raw_weak->untag()->value_ = Object::null();
  }

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(WeakProperty, Instance);
  friend class Class;
};

class WeakReference : public Instance {
 public:
  ObjectPtr target() const { return untag()->target(); }
  void set_target(const Object& target) const {
    untag()->set_target(target.ptr());
  }
  static intptr_t target_offset() {
    return OFFSET_OF(UntaggedWeakReference, target_);
  }

  static intptr_t type_arguments_offset() {
    return OFFSET_OF(UntaggedWeakReference, type_arguments_);
  }

  static WeakReferencePtr New(Heap::Space space = Heap::kNew);

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedWeakReference));
  }

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(WeakReference, Instance);
  friend class Class;
};

class FinalizerBase;
class FinalizerEntry : public Instance {
 public:
  ObjectPtr value() const { return untag()->value(); }
  void set_value(const Object& value) const { untag()->set_value(value.ptr()); }
  static intptr_t value_offset() {
    return OFFSET_OF(UntaggedFinalizerEntry, value_);
  }

  ObjectPtr detach() const { return untag()->detach(); }
  void set_detach(const Object& value) const {
    untag()->set_detach(value.ptr());
  }
  static intptr_t detach_offset() {
    return OFFSET_OF(UntaggedFinalizerEntry, detach_);
  }

  ObjectPtr token() const { return untag()->token(); }
  void set_token(const Object& value) const { untag()->set_token(value.ptr()); }
  static intptr_t token_offset() {
    return OFFSET_OF(UntaggedFinalizerEntry, token_);
  }

  FinalizerBasePtr finalizer() const { return untag()->finalizer(); }
  void set_finalizer(const FinalizerBase& value) const;
  static intptr_t finalizer_offset() {
    return OFFSET_OF(UntaggedFinalizerEntry, finalizer_);
  }

  FinalizerEntryPtr next() const { return untag()->next(); }
  void set_next(const FinalizerEntry& value) const {
    untag()->set_next(value.ptr());
  }
  static intptr_t next_offset() {
    return OFFSET_OF(UntaggedFinalizerEntry, next_);
  }

  intptr_t external_size() const { return untag()->external_size(); }
  void set_external_size(intptr_t value) const {
    untag()->set_external_size(value);
  }
  static intptr_t external_size_offset() {
    return OFFSET_OF(UntaggedFinalizerEntry, external_size_);
  }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedFinalizerEntry));
  }

  // Allocates a new FinalizerEntry, initializing the external size (to 0) and
  // finalizer.
  //
  // Should only be used for object tests.
  //
  // Does not initialize `value`, `token`, and `detach` to allow for flexible
  // testing code setting those manually.
  //
  // Does _not_ add the entry to the finalizer. We could add the entry to
  // finalizer.all_entries.data, but we have no way of initializing the hashset
  // index.
  static FinalizerEntryPtr New(const FinalizerBase& finalizer,
                               Heap::Space space = Heap::kNew);

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(FinalizerEntry, Instance);
  friend class Class;
};

class FinalizerBase : public Instance {
 public:
  static intptr_t isolate_offset() {
    return OFFSET_OF(UntaggedFinalizerBase, isolate_);
  }
  Isolate* isolate() const { return untag()->isolate_; }
  void set_isolate(Isolate* value) const { untag()->isolate_ = value; }

  static intptr_t detachments_offset() {
    return OFFSET_OF(UntaggedFinalizerBase, detachments_);
  }

  LinkedHashSetPtr all_entries() const { return untag()->all_entries(); }
  void set_all_entries(const LinkedHashSet& value) const {
    untag()->set_all_entries(value.ptr());
  }
  static intptr_t all_entries_offset() {
    return OFFSET_OF(UntaggedFinalizerBase, all_entries_);
  }

  FinalizerEntryPtr entries_collected() const {
    return untag()->entries_collected();
  }
  void set_entries_collected(const FinalizerEntry& value) const {
    untag()->set_entries_collected(value.ptr());
  }
  static intptr_t entries_collected_offset() {
    return OFFSET_OF(UntaggedFinalizer, entries_collected_);
  }

 private:
  HEAP_OBJECT_IMPLEMENTATION(FinalizerBase, Instance);
  friend class Class;
};

class Finalizer : public FinalizerBase {
 public:
  static intptr_t type_arguments_offset() {
    return OFFSET_OF(UntaggedFinalizer, type_arguments_);
  }

  ObjectPtr callback() const { return untag()->callback(); }
  static intptr_t callback_offset() {
    return OFFSET_OF(UntaggedFinalizer, callback_);
  }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedFinalizer));
  }

  static FinalizerPtr New(Heap::Space space = Heap::kNew);

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(Finalizer, FinalizerBase);
  friend class Class;
};

class NativeFinalizer : public FinalizerBase {
 public:
  typedef void (*Callback)(void*);

  PointerPtr callback() const { return untag()->callback(); }
  void set_callback(const Pointer& value) const {
    untag()->set_callback(value.ptr());
  }
  static intptr_t callback_offset() {
    return OFFSET_OF(UntaggedNativeFinalizer, callback_);
  }

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedNativeFinalizer));
  }

  static NativeFinalizerPtr New(Heap::Space space = Heap::kNew);

  void RunCallback(const FinalizerEntry& entry,
                   const char* trace_context) const;

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(NativeFinalizer, FinalizerBase);
  friend class Class;
};

class MirrorReference : public Instance {
 public:
  ObjectPtr referent() const { return untag()->referent(); }

  void set_referent(const Object& referent) const {
    untag()->set_referent(referent.ptr());
  }

  AbstractTypePtr GetAbstractTypeReferent() const;

  ClassPtr GetClassReferent() const;

  FieldPtr GetFieldReferent() const;

  FunctionPtr GetFunctionReferent() const;

  FunctionTypePtr GetFunctionTypeReferent() const;

  LibraryPtr GetLibraryReferent() const;

  TypeParameterPtr GetTypeParameterReferent() const;

  static MirrorReferencePtr New(const Object& referent,
                                Heap::Space space = Heap::kNew);

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedMirrorReference));
  }

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(MirrorReference, Instance);
  friend class Class;
};

class UserTag : public Instance {
 public:
  uword tag() const { return untag()->tag(); }
  void set_tag(uword t) const {
    ASSERT(t >= UserTags::kUserTagIdOffset);
    ASSERT(t < UserTags::kUserTagIdOffset + UserTags::kMaxUserTags);
    StoreNonPointer(&untag()->tag_, t);
  }

  bool streamable() const { return untag()->streamable(); }
  void set_streamable(bool streamable) {
    StoreNonPointer(&untag()->streamable_, streamable);
  }

  static intptr_t tag_offset() { return OFFSET_OF(UntaggedUserTag, tag_); }

  StringPtr label() const { return untag()->label(); }

  UserTagPtr MakeActive() const;

  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedUserTag));
  }

  static UserTagPtr New(const String& label, Heap::Space space = Heap::kOld);
  static UserTagPtr DefaultTag();

  static bool TagTableIsFull(Thread* thread);
  static UserTagPtr FindTagById(uword tag_id);
  static UserTagPtr FindTagInIsolate(Isolate* isolate,
                                     Thread* thread,
                                     const String& label);

 private:
  static UserTagPtr FindTagInIsolate(Thread* thread, const String& label);
  static void AddTagToIsolate(Thread* thread, const UserTag& tag);

  void set_label(const String& tag_label) const {
    untag()->set_label(tag_label.ptr());
  }

  FINAL_HEAP_OBJECT_IMPLEMENTATION(UserTag, Instance);
  friend class Class;
};

// Represents abstract FutureOr class in dart:async.
class FutureOr : public Instance {
 public:
  static intptr_t InstanceSize() {
    return RoundedAllocationSize(sizeof(UntaggedFutureOr));
  }

  virtual TypeArgumentsPtr GetTypeArguments() const {
    return untag()->type_arguments();
  }
  static intptr_t type_arguments_offset() {
    return OFFSET_OF(UntaggedFutureOr, type_arguments_);
  }

 private:
  FINAL_HEAP_OBJECT_IMPLEMENTATION(FutureOr, Instance);

  friend class Class;
};

// Breaking cycles and loops.
ClassPtr Object::clazz() const {
  uword raw_value = static_cast<uword>(ptr_);
  if ((raw_value & kSmiTagMask) == kSmiTag) {
    return Smi::Class();
  }
  ASSERT(!IsolateGroup::Current()->compaction_in_progress());
  return IsolateGroup::Current()->class_table()->At(ptr()->GetClassId());
}

DART_FORCE_INLINE
void Object::SetPtr(ObjectPtr value, intptr_t default_cid) {
  ptr_ = value;
  intptr_t cid = value->GetClassIdMayBeSmi();
  // Free-list elements cannot be wrapped in a handle.
  ASSERT(cid != kFreeListElement);
  ASSERT(cid != kForwardingCorpse);
  if (cid == kNullCid) {
    cid = default_cid;
  } else if (cid >= kNumPredefinedCids) {
    cid = kInstanceCid;
  }
  set_vtable(builtin_vtables_[cid]);
}

intptr_t Field::HostOffset() const {
  ASSERT(is_instance());  // Valid only for dart instance fields.
  return (Smi::Value(untag()->host_offset_or_field_id()) * kCompressedWordSize);
}

intptr_t Field::TargetOffset() const {
  ASSERT(is_instance());  // Valid only for dart instance fields.
#if !defined(DART_PRECOMPILED_RUNTIME)
  return (untag()->target_offset_ * compiler::target::kCompressedWordSize);
#else
  return HostOffset();
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)
}

inline intptr_t Field::TargetOffsetOf(const FieldPtr field) {
#if !defined(DART_PRECOMPILED_RUNTIME)
  return field->untag()->target_offset_;
#else
  return Smi::Value(field->untag()->host_offset_or_field_id());
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)
}

void Field::SetOffset(intptr_t host_offset_in_bytes,
                      intptr_t target_offset_in_bytes) const {
  ASSERT(is_instance());  // Valid only for dart instance fields.
  ASSERT(kCompressedWordSize != 0);
  untag()->set_host_offset_or_field_id(
      Smi::New(host_offset_in_bytes / kCompressedWordSize));
#if !defined(DART_PRECOMPILED_RUNTIME)
  ASSERT(compiler::target::kCompressedWordSize != 0);
  StoreNonPointer(
      &untag()->target_offset_,
      target_offset_in_bytes / compiler::target::kCompressedWordSize);
#else
  ASSERT(host_offset_in_bytes == target_offset_in_bytes);
#endif  //  !defined(DART_PRECOMPILED_RUNTIME)
}

ObjectPtr Field::StaticValue() const {
  ASSERT(is_static());  // Valid only for static dart fields.
  return Isolate::Current()->field_table()->At(field_id());
}

inline intptr_t Field::field_id() const {
  return Smi::Value(untag()->host_offset_or_field_id());
}

void Field::set_field_id(intptr_t field_id) const {
  DEBUG_ASSERT(
      IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
  set_field_id_unsafe(field_id);
}

void Field::set_field_id_unsafe(intptr_t field_id) const {
  ASSERT(is_static());
  untag()->set_host_offset_or_field_id(Smi::New(field_id));
}

void Context::SetAt(intptr_t index, const Object& value) const {
  untag()->set_element(index, value.ptr());
}

intptr_t Instance::GetNativeField(int index) const {
  ASSERT(IsValidNativeIndex(index));
  NoSafepointScope no_safepoint;
  TypedDataPtr native_fields = static_cast<TypedDataPtr>(
      NativeFieldsAddr()->Decompress(untag()->heap_base()));
  if (native_fields == TypedData::null()) {
    return 0;
  }
  return reinterpret_cast<intptr_t*>(native_fields->untag()->data())[index];
}

void Instance::GetNativeFields(uint16_t num_fields,
                               intptr_t* field_values) const {
  NoSafepointScope no_safepoint;
  ASSERT(num_fields == NumNativeFields());
  ASSERT(field_values != NULL);
  TypedDataPtr native_fields = static_cast<TypedDataPtr>(
      NativeFieldsAddr()->Decompress(untag()->heap_base()));
  if (native_fields == TypedData::null()) {
    for (intptr_t i = 0; i < num_fields; i++) {
      field_values[i] = 0;
    }
  }
  intptr_t* fields =
      reinterpret_cast<intptr_t*>(native_fields->untag()->data());
  for (intptr_t i = 0; i < num_fields; i++) {
    field_values[i] = fields[i];
  }
}

bool String::Equals(const String& str) const {
  if (ptr() == str.ptr()) {
    return true;  // Both handles point to the same raw instance.
  }
  if (str.IsNull()) {
    return false;
  }
  if (IsCanonical() && str.IsCanonical()) {
    return false;  // Two symbols that aren't identical aren't equal.
  }
  if (HasHash() && str.HasHash() && (Hash() != str.Hash())) {
    return false;  // Both sides have hash codes and they do not match.
  }
  return Equals(str, 0, str.Length());
}

intptr_t Library::UrlHash() const {
  intptr_t result = String::GetCachedHash(url());
  ASSERT(result != 0);
  return result;
}

void MegamorphicCache::SetEntry(const Array& array,
                                intptr_t index,
                                const Smi& class_id,
                                const Object& target) {
  ASSERT(target.IsNull() || target.IsFunction() || target.IsSmi());
  array.SetAt((index * kEntryLength) + kClassIdIndex, class_id);
  array.SetAt((index * kEntryLength) + kTargetFunctionIndex, target);
}

ObjectPtr MegamorphicCache::GetClassId(const Array& array, intptr_t index) {
  return array.At((index * kEntryLength) + kClassIdIndex);
}

ObjectPtr MegamorphicCache::GetTargetFunction(const Array& array,
                                              intptr_t index) {
  return array.At((index * kEntryLength) + kTargetFunctionIndex);
}

inline uword Type::Hash() const {
  ASSERT(IsFinalized());
  intptr_t result = Smi::Value(untag()->hash());
  if (result != 0) {
    return result;
  }
  return ComputeHash();
}

inline void Type::SetHash(intptr_t value) const {
  // This is only safe because we create a new Smi, which does not cause
  // heap allocation.
  untag()->set_hash(Smi::New(value));
}

inline uword FunctionType::Hash() const {
  ASSERT(IsFinalized());
  intptr_t result = Smi::Value(untag()->hash());
  if (result != 0) {
    return result;
  }
  return ComputeHash();
}

inline void FunctionType::SetHash(intptr_t value) const {
  // This is only safe because we create a new Smi, which does not cause
  // heap allocation.
  untag()->set_hash(Smi::New(value));
}

inline uword TypeParameter::Hash() const {
  ASSERT(IsFinalized() || IsBeingFinalized());  // Bound may not be finalized.
  intptr_t result = Smi::Value(untag()->hash());
  if (result != 0) {
    return result;
  }
  return ComputeHash();
}

inline void TypeParameter::SetHash(intptr_t value) const {
  // This is only safe because we create a new Smi, which does not cause
  // heap allocation.
  untag()->set_hash(Smi::New(value));
}

inline uword TypeArguments::Hash() const {
  if (IsNull()) return kAllDynamicHash;
  intptr_t result = Smi::Value(untag()->hash());
  if (result != 0) {
    return result;
  }
  return ComputeHash();
}

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

inline uint16_t String::CharAt(StringPtr str, intptr_t index) {
  switch (str->GetClassId()) {
    case kOneByteStringCid:
      return OneByteString::CharAt(static_cast<OneByteStringPtr>(str), index);
    case kTwoByteStringCid:
      return TwoByteString::CharAt(static_cast<TwoByteStringPtr>(str), index);
    case kExternalOneByteStringCid:
      return ExternalOneByteString::CharAt(
          static_cast<ExternalOneByteStringPtr>(str), index);
    case kExternalTwoByteStringCid:
      return ExternalTwoByteString::CharAt(
          static_cast<ExternalTwoByteStringPtr>(str), index);
  }
  UNREACHABLE();
  return 0;
}

// A view on an [Array] as a list of tuples, optionally starting at an offset.
//
// Example: We store a list of (kind, function, code) tuples into the
// [Code::static_calls_target_table] array of type [Array].
//
// This helper class can then be used via
//
//     using CallTableView = ArrayOfTuplesVied<
//         Code::Kind, std::tuple<Smi, Function, Code>>;
//
//     auto& array = Array::Handle(code.static_calls_targets_table());
//     CallTableView static_calls(array);
//
//     // Using convenient for loop.
//     auto& function = Function::Handle();
//     for (auto& call : static_calls) {
//       function = call.Get<Code::kSCallTableFunctionTarget>();
//       call.Set<Code::kSCallTableFunctionTarget>(function);
//     }
//
//     // Using manual loop.
//     auto& function = Function::Handle();
//     for (intptr_t i = 0; i < static_calls.Length(); ++i) {
//       auto call = static_calls[i];
//       function = call.Get<Code::kSCallTableFunctionTarget>();
//       call.Set<Code::kSCallTableFunctionTarget>(function);
//     }
//
//
// Template parameters:
//
//   * [EnumType] must be a normal enum which enumerates the entries of the
//     tuple
//
//   * [kStartOffset] is the offset at which the first tuple in the array
//     starts (can be 0).
//
//   * [TupleT] must be a std::tuple<...> where "..." are the heap object handle
//     classes (e.g. 'Code', 'Smi', 'Object')
template <typename EnumType, typename TupleT, int kStartOffset = 0>
class ArrayOfTuplesView {
 public:
  static constexpr intptr_t EntrySize = std::tuple_size<TupleT>::value;

  class Iterator;

  class TupleView {
   public:
    TupleView(const Array& array, intptr_t index)
        : array_(array), index_(index) {}

    template <EnumType kElement,
              std::memory_order order = std::memory_order_relaxed>
    typename std::tuple_element<kElement, TupleT>::type::ObjectPtrType Get()
        const {
      using object_type = typename std::tuple_element<kElement, TupleT>::type;
      return object_type::RawCast(array_.At<order>(index_ + kElement));
    }

    template <EnumType kElement,
              std::memory_order order = std::memory_order_relaxed>
    void Set(const typename std::tuple_element<kElement, TupleT>::type& value)
        const {
      array_.SetAt<order>(index_ + kElement, value);
    }

    intptr_t index() const { return (index_ - kStartOffset) / EntrySize; }

   private:
    const Array& array_;
    intptr_t index_;

    friend class Iterator;
  };

  class Iterator {
   public:
    Iterator(const Array& array, intptr_t index) : entry_(array, index) {}

    bool operator==(const Iterator& other) {
      return entry_.index_ == other.entry_.index_;
    }
    bool operator!=(const Iterator& other) {
      return entry_.index_ != other.entry_.index_;
    }

    const TupleView& operator*() const { return entry_; }

    Iterator& operator++() {
      entry_.index_ += EntrySize;
      return *this;
    }

   private:
    TupleView entry_;
  };

  explicit ArrayOfTuplesView(const Array& array) : array_(array), index_(-1) {
    ASSERT(!array.IsNull());
    ASSERT(array.Length() >= kStartOffset);
    ASSERT((array.Length() - kStartOffset) % EntrySize == kStartOffset);
  }

  intptr_t Length() const {
    return (array_.Length() - kStartOffset) / EntrySize;
  }

  TupleView At(intptr_t i) const {
    return TupleView(array_, kStartOffset + i * EntrySize);
  }

  TupleView operator[](intptr_t i) const { return At(i); }

  Iterator begin() const { return Iterator(array_, kStartOffset); }

  Iterator end() const {
    return Iterator(array_, kStartOffset + Length() * EntrySize);
  }

 private:
  const Array& array_;
  intptr_t index_;
};

using InvocationDispatcherTable =
    ArrayOfTuplesView<Class::InvocationDispatcherEntry,
                      std::tuple<String, Array, Function>>;

using StaticCallsTable =
    ArrayOfTuplesView<Code::SCallTableEntry, std::tuple<Smi, Object, Function>>;

using StaticCallsTableEntry = StaticCallsTable::TupleView;

using SubtypeTestCacheTable = ArrayOfTuplesView<SubtypeTestCache::Entries,
                                                std::tuple<Object,
                                                           Object,
                                                           AbstractType,
                                                           TypeArguments,
                                                           TypeArguments,
                                                           TypeArguments,
                                                           TypeArguments,
                                                           TypeArguments>>;

using MegamorphicCacheEntries =
    ArrayOfTuplesView<MegamorphicCache::EntryType, std::tuple<Smi, Object>>;

void DumpTypeTable(Isolate* isolate);
void DumpTypeParameterTable(Isolate* isolate);
void DumpTypeArgumentsTable(Isolate* isolate);

EntryPointPragma FindEntryPointPragma(IsolateGroup* isolate_group,
                                      const Array& metadata,
                                      Field* reusable_field_handle,
                                      Object* reusable_object_handle);

DART_WARN_UNUSED_RESULT
ErrorPtr EntryPointFieldInvocationError(const String& getter_name);

DART_WARN_UNUSED_RESULT
ErrorPtr EntryPointMemberInvocationError(const Object& member);

#undef PRECOMPILER_WSR_FIELD_DECLARATION

}  // namespace dart

#endif  // RUNTIME_VM_OBJECT_H_
