1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_OBJECTS_LAYOUT_DESCRIPTOR_H_ 6 #define V8_OBJECTS_LAYOUT_DESCRIPTOR_H_ 7 8 #include <iosfwd> 9 10 #include "src/objects/fixed-array.h" 11 12 // Has to be the last include (doesn't have include guards): 13 #include "src/objects/object-macros.h" 14 15 namespace v8 { 16 namespace internal { 17 18 // LayoutDescriptor is a bit vector defining which fields contain non-tagged 19 // values. It could either be a fixed typed array (slow form) or a Smi 20 // if the length fits (fast form). 21 // Each bit in the layout represents a FIELD. The bits are referenced by 22 // field_index which is a field number. If the bit is set then the corresponding 23 // field contains a non-tagged value and therefore must be skipped by GC. 24 // Otherwise the field is considered tagged. If the queried bit lays "outside" 25 // of the descriptor then the field is also considered tagged. 26 // Once a layout descriptor is created it is allowed only to append properties 27 // to it. GC uses layout descriptors to iterate objects. Avoid heap pointers 28 // in a layout descriptor because they can lead to data races in GC when 29 // GC moves objects in parallel. 30 class V8_EXPORT_PRIVATE LayoutDescriptor : public ByteArray { 31 public: 32 V8_INLINE bool IsTagged(int field_index); 33 34 // Queries the contiguous region of fields that are either tagged or not. 35 // Returns true if the given field is tagged or false otherwise and writes 36 // the length of the contiguous region to |out_sequence_length|. 37 // If the sequence is longer than |max_sequence_length| then 38 // |out_sequence_length| is set to |max_sequence_length|. 39 bool IsTagged(int field_index, int max_sequence_length, 40 int* out_sequence_length); 41 42 // Returns true if this is a layout of the object having only tagged fields. 43 V8_INLINE bool IsFastPointerLayout(); 44 V8_INLINE static bool IsFastPointerLayout(Object layout_descriptor); 45 46 // Returns true if the layout descriptor is in non-Smi form. 47 V8_INLINE bool IsSlowLayout(); 48 49 DECL_CAST(LayoutDescriptor) 50 51 V8_INLINE static LayoutDescriptor cast_gc_safe(Object object); 52 53 // Builds layout descriptor optimized for given |map| by |num_descriptors| 54 // elements of given descriptors array. The |map|'s descriptors could be 55 // different. 56 static Handle<LayoutDescriptor> New(Isolate* isolate, Handle<Map> map, 57 Handle<DescriptorArray> descriptors, 58 int num_descriptors); 59 60 // Modifies |map|'s layout descriptor or creates a new one if necessary by 61 // appending property with |details| to it. 62 static Handle<LayoutDescriptor> ShareAppend(Isolate* isolate, Handle<Map> map, 63 PropertyDetails details); 64 65 // Creates new layout descriptor by appending property with |details| to 66 // |map|'s layout descriptor and if it is still fast then returns it. 67 // Otherwise the |full_layout_descriptor| is returned. 68 static Handle<LayoutDescriptor> AppendIfFastOrUseFull( 69 Isolate* isolate, Handle<Map> map, PropertyDetails details, 70 Handle<LayoutDescriptor> full_layout_descriptor); 71 72 // Layout descriptor that corresponds to an object all fields of which are 73 // tagged (FastPointerLayout). 74 V8_INLINE static LayoutDescriptor FastPointerLayout(); 75 76 // Check that this layout descriptor corresponds to given map. 77 bool IsConsistentWithMap(Map map, bool check_tail = false); 78 79 // Trims this layout descriptor to given number of descriptors. This happens 80 // only when corresponding descriptors array is trimmed. 81 // The layout descriptor could be trimmed if it was slow or it could 82 // become fast. 83 LayoutDescriptor Trim(Heap* heap, Map map, DescriptorArray descriptors, 84 int num_descriptors); 85 86 #ifdef OBJECT_PRINT 87 // For our gdb macros, we should perhaps change these in the future. 88 void Print(); 89 90 void ShortPrint(std::ostream& os); 91 void Print(std::ostream& os); // NOLINT 92 #endif 93 94 // Capacity of layout descriptors in bits. 95 V8_INLINE int capacity(); 96 97 static Handle<LayoutDescriptor> NewForTesting(Isolate* isolate, int length); 98 LayoutDescriptor SetTaggedForTesting(int field_index, bool tagged); 99 100 private: 101 // Exclude sign-bit to simplify encoding. 102 static constexpr int kBitsInSmiLayout = 103 SmiValuesAre32Bits() ? 32 : kSmiValueSize - 1; 104 105 static const int kBitsPerLayoutWord = 32; 106 107 V8_INLINE int number_of_layout_words(); 108 V8_INLINE uint32_t get_layout_word(int index) const; 109 V8_INLINE void set_layout_word(int index, uint32_t value); 110 111 V8_INLINE static Handle<LayoutDescriptor> New(Isolate* isolate, int length); 112 V8_INLINE static LayoutDescriptor FromSmi(Smi smi); 113 114 V8_INLINE static bool InobjectUnboxedField(int inobject_properties, 115 PropertyDetails details); 116 117 // Calculates minimal layout descriptor capacity required for given 118 // |map|, |descriptors| and |num_descriptors|. 119 V8_INLINE static int CalculateCapacity(Map map, DescriptorArray descriptors, 120 int num_descriptors); 121 122 // Calculates the length of the slow-mode backing store array by given layout 123 // descriptor length. 124 V8_INLINE static int GetSlowModeBackingStoreLength(int length); 125 126 // Fills in clean |layout_descriptor| according to given |map|, |descriptors| 127 // and |num_descriptors|. 128 V8_INLINE static LayoutDescriptor Initialize( 129 LayoutDescriptor layout_descriptor, Map map, DescriptorArray descriptors, 130 int num_descriptors); 131 132 static Handle<LayoutDescriptor> EnsureCapacity( 133 Isolate* isolate, Handle<LayoutDescriptor> layout_descriptor, 134 int new_capacity); 135 136 // Returns false if requested field_index is out of bounds. 137 V8_INLINE bool GetIndexes(int field_index, int* layout_word_index, 138 int* layout_bit_index); 139 140 V8_INLINE V8_WARN_UNUSED_RESULT LayoutDescriptor SetRawData(int field_index); 141 142 V8_INLINE V8_WARN_UNUSED_RESULT LayoutDescriptor SetTagged(int field_index, 143 bool tagged); 144 145 OBJECT_CONSTRUCTORS(LayoutDescriptor, ByteArray); 146 }; 147 148 // LayoutDescriptorHelper is a helper class for querying layout descriptor 149 // about whether the field at given offset is tagged or not. 150 class LayoutDescriptorHelper { 151 public: 152 inline explicit LayoutDescriptorHelper(Map map); 153 all_fields_tagged()154 bool all_fields_tagged() { return all_fields_tagged_; } 155 inline bool IsTagged(int offset_in_bytes); 156 157 // Queries the contiguous region of fields that are either tagged or not. 158 // Returns true if fields starting at |offset_in_bytes| are tagged or false 159 // otherwise and writes the offset of the end of the contiguous region to 160 // |out_end_of_contiguous_region_offset|. The |end_offset| value is the 161 // upper bound for |out_end_of_contiguous_region_offset|. 162 V8_EXPORT_PRIVATE bool IsTagged(int offset_in_bytes, int end_offset, 163 int* out_end_of_contiguous_region_offset); 164 165 private: 166 bool all_fields_tagged_; 167 int header_size_; 168 LayoutDescriptor layout_descriptor_; 169 }; 170 } // namespace internal 171 } // namespace v8 172 173 #include "src/objects/object-macros-undef.h" 174 175 #endif // V8_OBJECTS_LAYOUT_DESCRIPTOR_H_ 176