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

#include "platform/thread_sanitizer.h"

#include "vm/compiler/runtime_api.h"

#include "vm/object.h"

#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/backend/flow_graph_compiler.h"
#include "vm/compiler/runtime_offsets_list.h"
#include "vm/dart_api_state.h"
#include "vm/dart_entry.h"
#include "vm/longjump.h"
#include "vm/native_arguments.h"
#include "vm/native_entry.h"
#include "vm/object_store.h"
#include "vm/runtime_entry.h"
#include "vm/symbols.h"
#include "vm/timeline.h"
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

namespace dart {
namespace compiler {
namespace target {

#include "vm/compiler/runtime_offsets_extracted.h"

bool IsSmi(int64_t v) {
  return Utils::IsInt(kSmiBits + 1, v);
}

bool WillAllocateNewOrRememberedObject(intptr_t instance_size) {
  ASSERT(Utils::IsAligned(instance_size, ObjectAlignment::kObjectAlignment));
  return dart::IsAllocatableInNewSpace(instance_size);
}

bool WillAllocateNewOrRememberedContext(intptr_t num_context_variables) {
  if (!dart::Context::IsValidLength(num_context_variables)) return false;
  return dart::IsAllocatableInNewSpace(
      dart::Context::InstanceSize(num_context_variables));
}

bool WillAllocateNewOrRememberedArray(intptr_t length) {
  if (!dart::Array::IsValidLength(length)) return false;
  return !dart::Array::UseCardMarkingForAllocation(length);
}

}  // namespace target
}  // namespace compiler
}  // namespace dart

#if !defined(DART_PRECOMPILED_RUNTIME)

namespace dart {
namespace compiler {

bool IsSameObject(const Object& a, const Object& b) {
  if (a.IsInstance() && b.IsInstance()) {
    return Instance::Cast(a).IsIdenticalTo(Instance::Cast(b));
  }
  return a.ptr() == b.ptr();
}

bool IsEqualType(const AbstractType& a, const AbstractType& b) {
  return a.Equals(b);
}

bool IsDoubleType(const AbstractType& type) {
  return type.IsDoubleType();
}

bool IsBoolType(const AbstractType& type) {
  return type.IsBoolType();
}

bool IsSubtypeOfInt(const AbstractType& type) {
  return type.IsIntType() || type.IsIntegerImplementationType() ||
         type.IsSmiType() || type.IsMintType();
}

bool IsSmiType(const AbstractType& type) {
  return type.IsSmiType();
}

#if defined(DEBUG)
bool IsNotTemporaryScopedHandle(const Object& obj) {
  return obj.IsNotTemporaryScopedHandle();
}
#endif

#define DO(clazz)                                                              \
  bool Is##clazz##Handle(const Object& obj) {                                  \
    return obj.Is##clazz();                                                    \
  }
CLASS_LIST_FOR_HANDLES(DO)
#undef DO

bool IsInOldSpace(const Object& obj) {
  return obj.IsSmi() || obj.IsOld();
}

intptr_t ObjectHash(const Object& obj) {
  if (obj.IsNull()) {
    return kNullIdentityHash;
  }
  // TypeArguments should be handled before Instance as TypeArguments extends
  // Instance and TypeArguments::CanonicalizeHash just returns 0.
  if (obj.IsTypeArguments()) {
    return TypeArguments::Cast(obj).Hash();
  }
  if (obj.IsInstance()) {
    return Instance::Cast(obj).CanonicalizeHash();
  }
  if (obj.IsCode()) {
    return Code::Cast(obj).Hash();
  }
  if (obj.IsFunction()) {
    return Function::Cast(obj).Hash();
  }
  if (obj.IsField()) {
    return Field::Cast(obj).Hash();
  }
  if (obj.IsICData()) {
    return ICData::Cast(obj).Hash();
  }
  // Unlikely.
  return obj.GetClassId();
}

const char* ObjectToCString(const Object& obj) {
  return obj.ToCString();
}

void SetToNull(Object* obj) {
  *obj = Object::null();
}

Object& NewZoneHandle(Zone* zone) {
  return Object::ZoneHandle(zone, Object::null());
}

Object& NewZoneHandle(Zone* zone, const Object& obj) {
  return Object::ZoneHandle(zone, obj.ptr());
}

const Object& NullObject() {
  return Object::null_object();
}

const Object& SentinelObject() {
  return Object::sentinel();
}

const Bool& TrueObject() {
  return dart::Bool::True();
}

const Bool& FalseObject() {
  return dart::Bool::False();
}

const Object& EmptyTypeArguments() {
  return Object::empty_type_arguments();
}

const Type& DynamicType() {
  return dart::Type::dynamic_type();
}

const Type& ObjectType() {
  return Type::Handle(dart::Type::ObjectType());
}

const Type& VoidType() {
  return dart::Type::void_type();
}

const Type& IntType() {
  return Type::Handle(dart::Type::IntType());
}

const Class& GrowableObjectArrayClass() {
  auto object_store = IsolateGroup::Current()->object_store();
  return Class::Handle(object_store->growable_object_array_class());
}

const Class& MintClass() {
  auto object_store = IsolateGroup::Current()->object_store();
  return Class::Handle(object_store->mint_class());
}

const Class& DoubleClass() {
  auto object_store = IsolateGroup::Current()->object_store();
  return Class::Handle(object_store->double_class());
}

const Class& Float32x4Class() {
  auto object_store = IsolateGroup::Current()->object_store();
  return Class::Handle(object_store->float32x4_class());
}

const Class& Float64x2Class() {
  auto object_store = IsolateGroup::Current()->object_store();
  return Class::Handle(object_store->float64x2_class());
}

const Class& Int32x4Class() {
  auto object_store = IsolateGroup::Current()->object_store();
  return Class::Handle(object_store->int32x4_class());
}

const Class& ClosureClass() {
  auto object_store = IsolateGroup::Current()->object_store();
  return Class::Handle(object_store->closure_class());
}

const Array& ArgumentsDescriptorBoxed(intptr_t type_args_len,
                                      intptr_t num_arguments) {
  return Array::ZoneHandle(
      ArgumentsDescriptor::NewBoxed(type_args_len, num_arguments));
}

bool IsOriginalObject(const Object& object) {
  if (object.IsICData()) {
    return ICData::Cast(object).IsOriginal();
  } else if (object.IsField()) {
    return Field::Cast(object).IsOriginal();
  }
  return true;
}

const String& AllocateString(const char* buffer) {
  return String::ZoneHandle(String::New(buffer, dart::Heap::kOld));
}

bool HasIntegerValue(const dart::Object& object, int64_t* value) {
  if (object.IsInteger()) {
    *value = Integer::Cast(object).Value();
    return true;
  }
  return false;
}

int32_t CreateJitCookie() {
  return static_cast<int32_t>(Thread::Current()->random()->NextUInt32());
}

word TypedDataElementSizeInBytes(classid_t cid) {
  return dart::TypedData::ElementSizeInBytes(cid);
}

word TypedDataMaxNewSpaceElements(classid_t cid) {
  return (dart::kNewAllocatableSize - target::TypedData::HeaderSize()) /
         TypedDataElementSizeInBytes(cid);
}

const Field& LookupMathRandomStateFieldOffset() {
  const auto& math_lib = dart::Library::Handle(dart::Library::MathLibrary());
  ASSERT(!math_lib.IsNull());
  const auto& random_class = dart::Class::Handle(
      math_lib.LookupClassAllowPrivate(dart::Symbols::_Random()));
  ASSERT(!random_class.IsNull());
  const auto& state_field = dart::Field::ZoneHandle(
      random_class.LookupInstanceFieldAllowPrivate(dart::Symbols::_state()));
  return state_field;
}

const Field& LookupConvertUtf8DecoderScanFlagsField() {
  const auto& convert_lib =
      dart::Library::Handle(dart::Library::ConvertLibrary());
  ASSERT(!convert_lib.IsNull());
  const auto& _utf8decoder_class = dart::Class::Handle(
      convert_lib.LookupClassAllowPrivate(dart::Symbols::_Utf8Decoder()));
  ASSERT(!_utf8decoder_class.IsNull());
  const auto& scan_flags_field = dart::Field::ZoneHandle(
      _utf8decoder_class.LookupInstanceFieldAllowPrivate(
          dart::Symbols::_scanFlags()));
  return scan_flags_field;
}

word LookupFieldOffsetInBytes(const Field& field) {
  return field.TargetOffset();
}

#if defined(TARGET_ARCH_IA32)
uword SymbolsPredefinedAddress() {
  return reinterpret_cast<uword>(dart::Symbols::PredefinedAddress());
}
#endif

const Code& StubCodeAllocateArray() {
  return dart::StubCode::AllocateArray();
}

const Code& StubCodeSubtype2TestCache() {
  return dart::StubCode::Subtype2TestCache();
}

const Code& StubCodeSubtype3TestCache() {
  return dart::StubCode::Subtype3TestCache();
}

const Code& StubCodeSubtype4TestCache() {
  return dart::StubCode::Subtype4TestCache();
}

const Code& StubCodeSubtype6TestCache() {
  return dart::StubCode::Subtype6TestCache();
}

const Code& StubCodeSubtype7TestCache() {
  return dart::StubCode::Subtype7TestCache();
}

#define DEFINE_ALIAS(name)                                                     \
  const RuntimeEntry& k##name##RuntimeEntry(dart::k##name##RuntimeEntry);
RUNTIME_ENTRY_LIST(DEFINE_ALIAS)
#undef DEFINE_ALIAS

#define DEFINE_ALIAS(type, name, ...)                                          \
  const RuntimeEntry& k##name##RuntimeEntry(dart::k##name##RuntimeEntry);
LEAF_RUNTIME_ENTRY_LIST(DEFINE_ALIAS)
#undef DEFINE_ALIAS

void BailoutWithBranchOffsetError() {
  Thread::Current()->long_jump_base()->Jump(1, Object::branch_offset_error());
}

word RuntimeEntry::OffsetFromThread() const {
  return target::Thread::OffsetFromThread(runtime_entry_);
}

const char* RuntimeEntry::name() const {
  return runtime_entry_->name();
}

bool RuntimeEntry::is_leaf() const {
  return runtime_entry_->is_leaf();
}

intptr_t RuntimeEntry::argument_count() const {
  return runtime_entry_->argument_count();
}

namespace target {

const word kPageSize = dart::kPageSize;
const word kPageSizeInWords = dart::kPageSize / kWordSize;
const word kPageMask = dart::kPageMask;

static word TranslateOffsetInWordsToHost(word offset) {
  RELEASE_ASSERT((offset % kCompressedWordSize) == 0);
  return (offset / kCompressedWordSize) * dart::kCompressedWordSize;
}

bool SizeFitsInSizeTag(uword instance_size) {
  return dart::UntaggedObject::SizeTag::SizeFits(
      TranslateOffsetInWordsToHost(instance_size));
}

uword MakeTagWordForNewSpaceObject(classid_t cid, uword instance_size) {
  return dart::UntaggedObject::SizeTag::encode(
             TranslateOffsetInWordsToHost(instance_size)) |
         dart::UntaggedObject::ClassIdTag::encode(cid) |
         dart::UntaggedObject::NewOrEvacuationCandidateBit::encode(true) |
         dart::UntaggedObject::AlwaysSetBit::encode(true) |
         dart::UntaggedObject::NotMarkedBit::encode(true) |
         dart::UntaggedObject::ImmutableBit::encode(
             dart::Object::ShouldHaveImmutabilityBitSet(cid));
}

word Object::tags_offset() {
  return 0;
}

const word UntaggedObject::kCardRememberedBit =
    dart::UntaggedObject::CardRememberedBit::shift();

const word UntaggedObject::kCanonicalBit =
    dart::UntaggedObject::CanonicalBit::shift();

const word UntaggedObject::kNewOrEvacuationCandidateBit =
    dart::UntaggedObject::NewOrEvacuationCandidateBit::shift();

const word UntaggedObject::kOldAndNotRememberedBit =
    dart::UntaggedObject::OldAndNotRememberedBit::shift();

const word UntaggedObject::kNotMarkedBit =
    dart::UntaggedObject::NotMarkedBit::shift();

const word UntaggedObject::kImmutableBit =
    dart::UntaggedObject::ImmutableBit::shift();

const word UntaggedObject::kSizeTagPos =
    dart::UntaggedObject::SizeTagBits::shift();

const word UntaggedObject::kSizeTagSize =
    dart::UntaggedObject::SizeTagBits::bitsize();

const word UntaggedObject::kClassIdTagPos =
    dart::UntaggedObject::ClassIdTag::shift();

const word UntaggedObject::kClassIdTagSize =
    dart::UntaggedObject::kClassIdTagSize;

#if defined(HASH_IN_OBJECT_HEADER)
const word UntaggedObject::kHashTagPos = dart::UntaggedObject::HashTag::shift();

const word UntaggedObject::kHashTagSize =
    dart::UntaggedObject::HashTag::bitsize();
#endif

const word UntaggedObject::kSizeTagMaxSizeTag =
    dart::UntaggedObject::SizeTag::kMaxSizeTagInUnitsOfAlignment *
    ObjectAlignment::kObjectAlignment;

const word UntaggedObject::kTagBitsSizeTagPos =
    dart::UntaggedObject::SizeTagBits::shift();

const word UntaggedAbstractType::kTypeStateFinalizedInstantiated =
    dart::UntaggedAbstractType::kFinalizedInstantiated;
const word UntaggedAbstractType::kTypeStateShift =
    dart::UntaggedAbstractType::TypeStateBits::shift();
const word UntaggedAbstractType::kTypeStateBits =
    dart::UntaggedAbstractType::TypeStateBits::bitsize();
const word UntaggedAbstractType::kNullabilityMask =
    dart::UntaggedAbstractType::NullabilityBit::mask();

const word UntaggedType::kTypeClassIdShift =
    dart::UntaggedType::TypeClassIdBits::shift();

const word UntaggedTypeParameter::kIsFunctionTypeParameterBit =
    dart::UntaggedTypeParameter::IsFunctionTypeParameter::shift();

const word UntaggedObject::kBarrierOverlapShift =
    dart::UntaggedObject::kBarrierOverlapShift;

const word UntaggedObject::kGenerationalBarrierMask =
    dart::UntaggedObject::kGenerationalBarrierMask;

const word UntaggedObject::kIncrementalBarrierMask =
    dart::UntaggedObject::kIncrementalBarrierMask;

bool IsTypedDataClassId(intptr_t cid) {
  return dart::IsTypedDataClassId(cid);
}

const word Class::kNoTypeArguments = dart::Class::kNoTypeArguments;

classid_t Class::GetId(const dart::Class& handle) {
  return handle.id();
}

static word TranslateOffsetInWords(word offset) {
  RELEASE_ASSERT((offset % dart::kWordSize) == 0);
  return (offset / dart::kWordSize) * kWordSize;
}

static uword GetInstanceSizeImpl(const dart::Class& handle) {
  switch (handle.id()) {
    case kMintCid:
      return Mint::InstanceSize();
    case kDoubleCid:
      return Double::InstanceSize();
    case kInt32x4Cid:
      return Int32x4::InstanceSize();
    case kFloat32x4Cid:
      return Float32x4::InstanceSize();
    case kFloat64x2Cid:
      return Float64x2::InstanceSize();
    case kObjectCid:
      return Object::InstanceSize();
    case kInstanceCid:
      return Instance::InstanceSize();
    case kGrowableObjectArrayCid:
      return GrowableObjectArray::InstanceSize();
    case kClosureCid:
      return Closure::InstanceSize();
    case kTypedDataBaseCid:
      return TypedDataBase::InstanceSize();
    case kMapCid:
      return Map::InstanceSize();
    case kSetCid:
      return Set::InstanceSize();
    case kUnhandledExceptionCid:
      return UnhandledException::InstanceSize();
    case kWeakPropertyCid:
      return WeakProperty::InstanceSize();
    case kWeakReferenceCid:
      return WeakReference::InstanceSize();
    case kFinalizerCid:
      return Finalizer::InstanceSize();
    case kFinalizerEntryCid:
      return FinalizerEntry::InstanceSize();
    case kNativeFinalizerCid:
      return NativeFinalizer::InstanceSize();
    case kByteBufferCid:
    case kByteDataViewCid:
    case kUnmodifiableByteDataViewCid:
    case kPointerCid:
    case kDynamicLibraryCid:
#define HANDLE_CASE(clazz) case kFfi##clazz##Cid:
      CLASS_LIST_FFI_TYPE_MARKER(HANDLE_CASE)
#undef HANDLE_CASE
#define HANDLE_CASE(clazz)                                                     \
  case kTypedData##clazz##Cid:                                                 \
  case kTypedData##clazz##ViewCid:                                             \
  case kExternalTypedData##clazz##Cid:                                         \
  case kUnmodifiableTypedData##clazz##ViewCid:
      CLASS_LIST_TYPED_DATA(HANDLE_CASE)
#undef HANDLE_CASE
      return handle.target_instance_size();
    default:
      if (handle.id() >= kNumPredefinedCids) {
        return handle.target_instance_size();
      }
  }
  FATAL("Unsupported class for size translation: %s (id=%" Pd
        ", kNumPredefinedCids=%" Pd ")\n",
        handle.ToCString(), handle.id(), kNumPredefinedCids);
  return -1;
}

uword Class::GetInstanceSize(const dart::Class& handle) {
  return Utils::RoundUp(GetInstanceSizeImpl(handle),
                        ObjectAlignment::kObjectAlignment);
}

// Currently, we only have compressed pointers on the target if we also have
// compressed pointers on the host, since only 64-bit architectures can have
// compressed pointers and there is no 32-bit host/64-bit target combination.
// Thus, we cheat a little here and use the host information about compressed
// pointers for the target, instead of storing this information in the extracted
// offsets information.
bool Class::HasCompressedPointers(const dart::Class& handle) {
  return handle.HasCompressedPointers();
}

intptr_t Class::NumTypeArguments(const dart::Class& klass) {
  return klass.NumTypeArguments();
}

bool Class::HasTypeArgumentsField(const dart::Class& klass) {
  return klass.host_type_arguments_field_offset() !=
         dart::Class::kNoTypeArguments;
}

intptr_t Class::TypeArgumentsFieldOffset(const dart::Class& klass) {
  return klass.target_type_arguments_field_offset();
}

bool Class::TraceAllocation(const dart::Class& klass) {
  return klass.TraceAllocation(dart::IsolateGroup::Current());
}

word Instance::first_field_offset() {
  return TranslateOffsetInWords(dart::Instance::NextFieldOffset());
}

word Instance::native_fields_array_offset() {
  return TranslateOffsetInWords(dart::Instance::NativeFieldsOffset());
}

word Instance::DataOffsetFor(intptr_t cid) {
  if (dart::IsExternalTypedDataClassId(cid)) {
    // Elements start at offset 0 of the external data.
    return 0;
  }
  if (dart::IsTypedDataClassId(cid)) {
    return TypedData::payload_offset();
  }
  switch (cid) {
    case kArrayCid:
    case kImmutableArrayCid:
      return Array::data_offset();
    case kTypeArgumentsCid:
      return TypeArguments::types_offset();
    case kOneByteStringCid:
      return OneByteString::data_offset();
    case kTwoByteStringCid:
      return TwoByteString::data_offset();
    case kRecordCid:
      return Record::field_offset(0);
    default:
      UNIMPLEMENTED();
      return Array::data_offset();
  }
}

word Instance::ElementSizeFor(intptr_t cid) {
  if (dart::IsExternalTypedDataClassId(cid) || dart::IsTypedDataClassId(cid) ||
      dart::IsTypedDataViewClassId(cid) ||
      dart::IsUnmodifiableTypedDataViewClassId(cid)) {
    return dart::TypedDataBase::ElementSizeInBytes(cid);
  }
  switch (cid) {
    case kArrayCid:
    case kImmutableArrayCid:
      return kCompressedWordSize;
    case kTypeArgumentsCid:
      return kCompressedWordSize;
    case kOneByteStringCid:
      return dart::OneByteString::kBytesPerElement;
    case kTwoByteStringCid:
      return dart::TwoByteString::kBytesPerElement;
    default:
      UNIMPLEMENTED();
      return 0;
  }
}

word ICData::CodeIndexFor(word num_args) {
  return dart::ICData::CodeIndexFor(num_args);
}

word ICData::CountIndexFor(word num_args) {
  return dart::ICData::CountIndexFor(num_args);
}

word ICData::TargetIndexFor(word num_args) {
  return dart::ICData::TargetIndexFor(num_args);
}

word ICData::ExactnessIndexFor(word num_args) {
  return dart::ICData::ExactnessIndexFor(num_args);
}

word ICData::TestEntryLengthFor(word num_args, bool exactness_check) {
  return dart::ICData::TestEntryLengthFor(num_args, exactness_check);
}

word ICData::EntryPointIndexFor(word num_args) {
  return dart::ICData::EntryPointIndexFor(num_args);
}

const word MegamorphicCache::kSpreadFactor =
    dart::MegamorphicCache::kSpreadFactor;

// Currently we have two different axes for offset generation:
//
//  * Target architecture
//  * DART_PRECOMPILED_RUNTIME (i.e, AOT vs. JIT)
//
// TODO(dartbug.com/43646): Add DART_PRECOMPILER as another axis.

#define DEFINE_CONSTANT(Class, Name) const word Class::Name = Class##_##Name;

#define DEFINE_ARRAY_SIZEOF(clazz, name, ElementOffset)                        \
  word clazz::name() {                                                         \
    return 0;                                                                  \
  }                                                                            \
  word clazz::name(intptr_t length) {                                          \
    return RoundedAllocationSize(clazz::ElementOffset(length));                \
  }

#define DEFINE_PAYLOAD_SIZEOF(clazz, name, header)                             \
  word clazz::name() {                                                         \
    return 0;                                                                  \
  }                                                                            \
  word clazz::name(word payload_size) {                                        \
    return RoundedAllocationSize(clazz::header() + payload_size);              \
  }

#if defined(TARGET_ARCH_IA32)

#define DEFINE_FIELD(clazz, name)                                              \
  word clazz::name() {                                                         \
    return clazz##_##name;                                                     \
  }

#define DEFINE_ARRAY(clazz, name)                                              \
  word clazz::name(intptr_t index) {                                           \
    return clazz##_elements_start_offset + index * clazz##_element_size;       \
  }

#define DEFINE_SIZEOF(clazz, name, what)                                       \
  word clazz::name() {                                                         \
    return clazz##_##name;                                                     \
  }

#define DEFINE_RANGE(Class, Getter, Type, First, Last, Filter)                 \
  word Class::Getter(Type index) {                                             \
    return Class##_##Getter[static_cast<intptr_t>(index) -                     \
                            static_cast<intptr_t>(First)];                     \
  }

JIT_OFFSETS_LIST(DEFINE_FIELD,
                 DEFINE_ARRAY,
                 DEFINE_SIZEOF,
                 DEFINE_ARRAY_SIZEOF,
                 DEFINE_PAYLOAD_SIZEOF,
                 DEFINE_RANGE,
                 DEFINE_CONSTANT)

COMMON_OFFSETS_LIST(DEFINE_FIELD,
                    DEFINE_ARRAY,
                    DEFINE_SIZEOF,
                    DEFINE_ARRAY_SIZEOF,
                    DEFINE_PAYLOAD_SIZEOF,
                    DEFINE_RANGE,
                    DEFINE_CONSTANT)

#else

#define DEFINE_JIT_FIELD(clazz, name)                                          \
  word clazz::name() {                                                         \
    if (FLAG_precompiled_mode) {                                               \
      FATAL("Use of JIT-only field %s in precompiled mode",                    \
            #clazz "::" #name);                                                \
    }                                                                          \
    return clazz##_##name;                                                     \
  }

#define DEFINE_JIT_ARRAY(clazz, name)                                          \
  word clazz::name(intptr_t index) {                                           \
    if (FLAG_precompiled_mode) {                                               \
      FATAL("Use of JIT-only array %s in precompiled mode",                    \
            #clazz "::" #name);                                                \
    }                                                                          \
    return clazz##_elements_start_offset + index * clazz##_element_size;       \
  }

#define DEFINE_JIT_SIZEOF(clazz, name, what)                                   \
  word clazz::name() {                                                         \
    if (FLAG_precompiled_mode) {                                               \
      FATAL("Use of JIT-only sizeof %s in precompiled mode",                   \
            #clazz "::" #name);                                                \
    }                                                                          \
    return clazz##_##name;                                                     \
  }

#define DEFINE_JIT_RANGE(Class, Getter, Type, First, Last, Filter)             \
  word Class::Getter(Type index) {                                             \
    if (FLAG_precompiled_mode) {                                               \
      FATAL("Use of JIT-only range %s in precompiled mode",                    \
            #Class "::" #Getter);                                              \
    }                                                                          \
    return Class##_##Getter[static_cast<intptr_t>(index) -                     \
                            static_cast<intptr_t>(First)];                     \
  }

JIT_OFFSETS_LIST(DEFINE_JIT_FIELD,
                 DEFINE_JIT_ARRAY,
                 DEFINE_JIT_SIZEOF,
                 DEFINE_ARRAY_SIZEOF,
                 DEFINE_PAYLOAD_SIZEOF,
                 DEFINE_JIT_RANGE,
                 DEFINE_CONSTANT)

#undef DEFINE_JIT_FIELD
#undef DEFINE_JIT_ARRAY
#undef DEFINE_JIT_SIZEOF
#undef DEFINE_JIT_RANGE

#if defined(DART_PRECOMPILER)
// The following could check FLAG_precompiled_mode for more safety, but that
// causes problems for defining things like native Slots, where the definition
// cannot be based on a runtime flag. Instead, we limit the visibility of these
// definitions using DART_PRECOMPILER.

#define DEFINE_AOT_FIELD(clazz, name)                                          \
  word clazz::name() {                                                         \
    return AOT_##clazz##_##name;                                               \
  }

#define DEFINE_AOT_ARRAY(clazz, name)                                          \
  word clazz::name(intptr_t index) {                                           \
    return AOT_##clazz##_elements_start_offset +                               \
           index * AOT_##clazz##_element_size;                                 \
  }

#define DEFINE_AOT_SIZEOF(clazz, name, what)                                   \
  word clazz::name() {                                                         \
    return AOT_##clazz##_##name;                                               \
  }

#define DEFINE_AOT_RANGE(Class, Getter, Type, First, Last, Filter)             \
  word Class::Getter(Type index) {                                             \
    return AOT_##Class##_##Getter[static_cast<intptr_t>(index) -               \
                                  static_cast<intptr_t>(First)];               \
  }
#else
#define DEFINE_AOT_FIELD(clazz, name)                                          \
  word clazz::name() {                                                         \
    FATAL("Use of AOT-only field %s outside of the precompiler",               \
          #clazz "::" #name);                                                  \
  }

#define DEFINE_AOT_ARRAY(clazz, name)                                          \
  word clazz::name(intptr_t index) {                                           \
    FATAL("Use of AOT-only array %s outside of the precompiler",               \
          #clazz "::" #name);                                                  \
  }

#define DEFINE_AOT_SIZEOF(clazz, name, what)                                   \
  word clazz::name() {                                                         \
    FATAL("Use of AOT-only sizeof %s outside of the precompiler",              \
          #clazz "::" #name);                                                  \
  }

#define DEFINE_AOT_RANGE(Class, Getter, Type, First, Last, Filter)             \
  word Class::Getter(Type index) {                                             \
    FATAL("Use of AOT-only range %s outside of the precompiler",               \
          #Class "::" #Getter);                                                \
  }
#endif  // defined(DART_PRECOMPILER)

AOT_OFFSETS_LIST(DEFINE_AOT_FIELD,
                 DEFINE_AOT_ARRAY,
                 DEFINE_AOT_SIZEOF,
                 DEFINE_ARRAY_SIZEOF,
                 DEFINE_PAYLOAD_SIZEOF,
                 DEFINE_AOT_RANGE,
                 DEFINE_CONSTANT)

#undef DEFINE_AOT_FIELD
#undef DEFINE_AOT_ARRAY
#undef DEFINE_AOT_SIZEOF
#undef DEFINE_AOT_RANGE

#define DEFINE_FIELD(clazz, name)                                              \
  word clazz::name() {                                                         \
    return FLAG_precompiled_mode ? AOT_##clazz##_##name : clazz##_##name;      \
  }

#define DEFINE_ARRAY(clazz, name)                                              \
  word clazz::name(intptr_t index) {                                           \
    if (FLAG_precompiled_mode) {                                               \
      return AOT_##clazz##_elements_start_offset +                             \
             index * AOT_##clazz##_element_size;                               \
    } else {                                                                   \
      return clazz##_elements_start_offset + index * clazz##_element_size;     \
    }                                                                          \
  }

#define DEFINE_SIZEOF(clazz, name, what)                                       \
  word clazz::name() {                                                         \
    return FLAG_precompiled_mode ? AOT_##clazz##_##name : clazz##_##name;      \
  }

#define DEFINE_RANGE(Class, Getter, Type, First, Last, Filter)                 \
  word Class::Getter(Type index) {                                             \
    if (FLAG_precompiled_mode) {                                               \
      return AOT_##Class##_##Getter[static_cast<intptr_t>(index) -             \
                                    static_cast<intptr_t>(First)];             \
    } else {                                                                   \
      return Class##_##Getter[static_cast<intptr_t>(index) -                   \
                              static_cast<intptr_t>(First)];                   \
    }                                                                          \
  }

COMMON_OFFSETS_LIST(DEFINE_FIELD,
                    DEFINE_ARRAY,
                    DEFINE_SIZEOF,
                    DEFINE_ARRAY_SIZEOF,
                    DEFINE_PAYLOAD_SIZEOF,
                    DEFINE_RANGE,
                    DEFINE_CONSTANT)

#endif

#undef DEFINE_FIELD
#undef DEFINE_ARRAY
#undef DEFINE_SIZEOF
#undef DEFINE_RANGE
#undef DEFINE_PAYLOAD_SIZEOF
#undef DEFINE_CONSTANT

const word StoreBufferBlock::kSize = dart::StoreBufferBlock::kSize;

const word MarkingStackBlock::kSize = dart::MarkingStackBlock::kSize;

// For InstructionsSections and Instructions, we define these by hand, because
// they depend on flags or #defines.

// Used for InstructionsSection and Instructions methods, since we don't
// serialize Instructions objects in bare instructions mode, just payloads.
DART_FORCE_INLINE static bool BareInstructionsPayloads() {
  return FLAG_precompiled_mode;
}

word Instructions::HeaderSize() {
  return BareInstructionsPayloads()
             ? 0
             : Utils::RoundUp(UnalignedHeaderSize(), kNonBarePayloadAlignment);
}

word Instructions::InstanceSize() {
  return 0;
}

word Instructions::InstanceSize(word payload_size) {
  const intptr_t alignment = BareInstructionsPayloads()
                                 ? kBarePayloadAlignment
                                 : ObjectAlignment::kObjectAlignment;
  return Utils::RoundUp(Instructions::HeaderSize() + payload_size, alignment);
}

word Thread::stack_overflow_shared_stub_entry_point_offset(bool fpu_regs) {
  return fpu_regs ? stack_overflow_shared_with_fpu_regs_entry_point_offset()
                  : stack_overflow_shared_without_fpu_regs_entry_point_offset();
}

uword Thread::native_safepoint_state_unacquired() {
  return dart::Thread::native_safepoint_state_unacquired();
}

uword Thread::native_safepoint_state_acquired() {
  return dart::Thread::native_safepoint_state_acquired();
}

uword Thread::generated_execution_state() {
  return dart::Thread::ExecutionState::kThreadInGenerated;
}

uword Thread::native_execution_state() {
  return dart::Thread::ExecutionState::kThreadInNative;
}

uword Thread::vm_execution_state() {
  return dart::Thread::ExecutionState::kThreadInVM;
}

uword Thread::vm_tag_dart_id() {
  return dart::VMTag::kDartTagId;
}

uword Thread::exit_through_runtime_call() {
  return dart::Thread::kExitThroughRuntimeCall;
}

uword Thread::exit_through_ffi() {
  return dart::Thread::kExitThroughFfi;
}

word Thread::OffsetFromThread(const dart::Object& object) {
  auto host_offset = dart::Thread::OffsetFromThread(object);
  return object_null_offset() +
         TranslateOffsetInWords(host_offset -
                                dart::Thread::object_null_offset());
}

intptr_t Thread::OffsetFromThread(const dart::RuntimeEntry* runtime_entry) {
  auto host_offset = dart::Thread::OffsetFromThread(runtime_entry);
  return AllocateArray_entry_point_offset() +
         TranslateOffsetInWords(
             host_offset - dart::Thread::AllocateArray_entry_point_offset());
}

bool CanLoadFromThread(const dart::Object& object,
                       intptr_t* offset /* = nullptr */) {
  if (dart::Thread::CanLoadFromThread(object)) {
    if (offset != nullptr) {
      *offset = Thread::OffsetFromThread(object);
    }
    return true;
  }
  return false;
}

static_assert(
    kSmiBits <= dart::kSmiBits,
    "Expected that size of Smi on HOST is at least as large as on target.");

bool IsSmi(const dart::Object& a) {
  return a.IsSmi() && IsSmi(dart::Smi::Cast(a).Value());
}

word ToRawSmi(const dart::Object& a) {
  RELEASE_ASSERT(IsSmi(a));
  return static_cast<compressed_word>(static_cast<intptr_t>(a.ptr()));
}

word ToRawSmi(intptr_t value) {
  return dart::Smi::RawValue(value);
}

word SmiValue(const dart::Object& a) {
  RELEASE_ASSERT(IsSmi(a));
  return static_cast<word>(dart::Smi::Cast(a).Value());
}

bool IsDouble(const dart::Object& a) {
  return a.IsDouble();
}

double DoubleValue(const dart::Object& a) {
  RELEASE_ASSERT(IsDouble(a));
  return dart::Double::Cast(a).value();
}

#if defined(TARGET_ARCH_IA32)
uword Code::EntryPointOf(const dart::Code& code) {
  static_assert(kHostWordSize == kWordSize,
                "Can't embed raw pointers to runtime objects when host and "
                "target word sizes are different");
  return code.EntryPoint();
}

bool CanEmbedAsRawPointerInGeneratedCode(const dart::Object& obj) {
  return obj.IsSmi() || obj.InVMIsolateHeap();
}

word ToRawPointer(const dart::Object& a) {
  static_assert(kHostWordSize == kWordSize,
                "Can't embed raw pointers to runtime objects when host and "
                "target word sizes are different");
  return static_cast<word>(a.ptr());
}
#endif  // defined(TARGET_ARCH_IA32)

word RegExp::function_offset(classid_t cid, bool sticky) {
#if !defined(DART_COMPRESSED_POINTERS)
  return TranslateOffsetInWords(dart::RegExp::function_offset(cid, sticky));
#else
  // TODO(rmacnak): TranslateOffsetInWords doesn't account for, say, header
  // being 1 word and slots being half words.
  return dart::RegExp::function_offset(cid, sticky);
#endif
}

const word Symbols::kNumberOfOneCharCodeSymbols =
    dart::Symbols::kNumberOfOneCharCodeSymbols;
const word Symbols::kNullCharCodeSymbolOffset =
    dart::Symbols::kNullCharCodeSymbolOffset;

const word String::kHashBits = dart::String::kHashBits;

const uint8_t Nullability::kNullable =
    static_cast<uint8_t>(dart::Nullability::kNullable);
const uint8_t Nullability::kNonNullable =
    static_cast<uint8_t>(dart::Nullability::kNonNullable);

bool Heap::IsAllocatableInNewSpace(intptr_t instance_size) {
  return dart::IsAllocatableInNewSpace(instance_size);
}

word Field::OffsetOf(const dart::Field& field) {
  return field.TargetOffset();
}

word FieldTable::OffsetOf(const dart::Field& field) {
  return TranslateOffsetInWords(
      dart::FieldTable::FieldOffsetFor(field.field_id()));
}

word FreeListElement::FakeInstance::InstanceSize() {
  return 0;
}

word ForwardingCorpse::FakeInstance::InstanceSize() {
  return 0;
}

word Instance::NextFieldOffset() {
  return TranslateOffsetInWords(dart::Instance::NextFieldOffset());
}

intptr_t Array::index_at_offset(intptr_t offset_in_bytes) {
  return dart::Array::index_at_offset(
      TranslateOffsetInWordsToHost(offset_in_bytes));
}

intptr_t Record::field_index_at_offset(intptr_t offset_in_bytes) {
  return dart::Record::field_index_at_offset(
      TranslateOffsetInWordsToHost(offset_in_bytes));
}

word String::InstanceSize(word payload_size) {
  return RoundedAllocationSize(String::InstanceSize() + payload_size);
}

word LocalVarDescriptors::InstanceSize() {
  return 0;
}

word Integer::NextFieldOffset() {
  return TranslateOffsetInWords(dart::Integer::NextFieldOffset());
}

word Smi::InstanceSize() {
  return 0;
}

word Number::NextFieldOffset() {
  return TranslateOffsetInWords(dart::Number::NextFieldOffset());
}

void UnboxFieldIfSupported(const dart::Field& field,
                           const dart::AbstractType& type) {
  if (field.is_static() || field.is_late()) {
    return;
  }

  if (type.IsNullable()) {
    return;
  }

  classid_t cid = kIllegalCid;
  if (type.IsDoubleType()) {
    cid = kDoubleCid;
  } else if (type.IsFloat32x4Type()) {
    if (FlowGraphCompiler::SupportsUnboxedSimd128()) {
      cid = kFloat32x4Cid;
    }
  } else if (type.IsFloat64x2Type()) {
    if (FlowGraphCompiler::SupportsUnboxedSimd128()) {
      cid = kFloat64x2Cid;
    }
  }

  if (cid != kIllegalCid) {
    field.set_guarded_cid(cid);
    field.set_is_nullable(false);
    field.set_is_unboxed(true);
    field.set_guarded_list_length(dart::Field::kNoFixedLength);
    field.set_guarded_list_length_in_object_offset(
        dart::Field::kUnknownLengthOffset);
  }
}

}  // namespace target
}  // namespace compiler
}  // namespace dart

#else

namespace dart {
namespace compiler {
namespace target {

const word Array::kMaxElements = Array_kMaxElements;
const word Context::kMaxElements = Context_kMaxElements;
const word Record::kMaxElements = Record_kMaxElements;

const word RecordShape::kNumFieldsMask = RecordShape_kNumFieldsMask;
const word RecordShape::kMaxNumFields = RecordShape_kMaxNumFields;
const word RecordShape::kFieldNamesIndexShift =
    RecordShape_kFieldNamesIndexShift;
const word RecordShape::kFieldNamesIndexMask = RecordShape_kFieldNamesIndexMask;
const word RecordShape::kMaxFieldNamesIndex = RecordShape_kMaxFieldNamesIndex;

}  // namespace target
}  // namespace compiler
}  // namespace dart

#endif  // !defined(DART_PRECOMPILED_RUNTIME)
