// 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>(IsolateGroup::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_);
}

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)
