// Copyright 2019 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_OBJECTS_TAGGED_FIELD_H_ #define V8_OBJECTS_TAGGED_FIELD_H_ #include "src/base/atomicops.h" #include "src/base/macros.h" #include "src/base/template-meta-programming/functional.h" #include "src/common/globals.h" #include "src/common/ptr-compr.h" #include "src/objects/tagged-value.h" namespace v8::internal { // TaggedMember<T> represents an potentially compressed V8 tagged pointer, which // is intended to be used as a member of a V8 object class. // // TODO(leszeks): Merge with TaggedField. template <typename T, typename CompressionScheme = V8HeapCompressionScheme> class TaggedMember; // Base class for all TaggedMember<T> classes. // TODO(leszeks): Merge with TaggedImpl. TaggedMemberBase; template <typename T, typename CompressionScheme> class TaggedMember : public TaggedMemberBase { … }; static_assert(alignof(TaggedMember<Object>) == alignof(Tagged_t)); static_assert(sizeof(TaggedMember<Object>) == sizeof(Tagged_t)); template <typename T> class UnalignedValueMember { … }; class UnalignedDoubleMember : public UnalignedValueMember<double> { … }; static_assert …; static_assert …; // FLEXIBLE_ARRAY_MEMBER(T, name) represents a marker for a variable-sized // suffix of members for a type. // // It behaves as if it were the last member of a class, and creates an accessor // for `T* name()`. // // This macro is used instead of the C99 flexible array member syntax, because // // a) That syntax is only in C++ as an extension, // b) On all our major compilers, it doesn't allow the class to have // subclasses (which means it doesn't work for e.g. TaggedArrayBase or // BigIntBase), // c) The similar zero-length array extension _also_ doesn't allow subclasses // on some compilers (specifically, MSVC). // // On compilers that do support zero length arrays (i.e. not MSVC), we use one // of these instead of `this` pointer fiddling. This gives LLVM better // information for optimization, and gives us the warnings we'd want to have // (e.g. only allowing one FAM in a class, ensuring that OFFSET_OF_DATA_START is // only used on classes with a FAM) on clang -- the MSVC version then doesn't // check the same constraints, and relies on the code being equivalent enough. #if V8_CC_MSVC && !defined(__clang__) // MSVC doesn't support zero length arrays in base classes. Cast the // one-past-this value to a zero length array reference, so that the return // values match that in GCC/clang. #define FLEXIBLE_ARRAY_MEMBER … #else // GCC and clang allow zero length arrays in base classes. Return the zero // length array by reference, to avoid array-to-pointer decay which can lose // aliasing information. #define FLEXIBLE_ARRAY_MEMBER(Type, name) … #endif // OFFSET_OF_DATA_START(T) returns the offset of the FLEXIBLE_ARRAY_MEMBER of // the class T. #if V8_CC_MSVC && !defined(__clang__) #define OFFSET_OF_DATA_START … #else #define OFFSET_OF_DATA_START(Type) … #endif // This helper static class represents a tagged field of type T at offset // kFieldOffset inside some host HeapObject. // For full-pointer mode this type adds no overhead but when pointer // compression is enabled such class allows us to use proper decompression // function depending on the field type. template <typename T, int kFieldOffset = 0, typename CompressionScheme = V8HeapCompressionScheme> class TaggedField : public AllStatic { … }; template <typename T> class TaggedField<Tagged<T>> : public TaggedField<T> {}; template <typename T, int kFieldOffset> class TaggedField<Tagged<T>, kFieldOffset> : public TaggedField<T, kFieldOffset> {}; TaggedField<Tagged<T>, kFieldOffset, CompressionScheme>; } // namespace v8::internal #endif // V8_OBJECTS_TAGGED_FIELD_H_