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