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_FIELD_INDEX_H_ 6 #define V8_OBJECTS_FIELD_INDEX_H_ 7 8 // TODO(jkummerow): Consider forward-declaring instead. 9 #include "src/objects/internal-index.h" 10 #include "src/objects/property-details.h" 11 #include "src/utils/utils.h" 12 13 namespace v8 { 14 namespace internal { 15 16 class Map; 17 18 // Wrapper class to hold a field index, usually but not necessarily generated 19 // from a property index. When available, the wrapper class captures additional 20 // information to allow the field index to be translated back into the property 21 // index it was originally generated from. 22 class FieldIndex final { 23 public: 24 enum Encoding { kTagged, kDouble, kWord32 }; 25 FieldIndex()26 FieldIndex() : bit_field_(0) {} 27 28 static inline FieldIndex ForPropertyIndex( 29 Map map, int index, 30 Representation representation = Representation::Tagged()); 31 static inline FieldIndex ForInObjectOffset(int offset, Encoding encoding); 32 static inline FieldIndex ForDescriptor(Map map, 33 InternalIndex descriptor_index); 34 static inline FieldIndex ForDescriptor(PtrComprCageBase cage_base, Map map, 35 InternalIndex descriptor_index); 36 37 inline int GetLoadByFieldIndex() const; 38 is_inobject()39 bool is_inobject() const { return IsInObjectBits::decode(bit_field_); } 40 is_double()41 bool is_double() const { return EncodingBits::decode(bit_field_) == kDouble; } 42 offset()43 int offset() const { return OffsetBits::decode(bit_field_); } 44 bit_field()45 uint64_t bit_field() const { return bit_field_; } 46 47 // Zero-indexed from beginning of the object. index()48 int index() const { 49 DCHECK(IsAligned(offset(), kTaggedSize)); 50 return offset() / kTaggedSize; 51 } 52 outobject_array_index()53 int outobject_array_index() const { 54 DCHECK(!is_inobject()); 55 return index() - first_inobject_property_offset() / kTaggedSize; 56 } 57 58 // Zero-based from the first inobject property. Overflows to out-of-object 59 // properties. property_index()60 int property_index() const { 61 int result = index() - first_inobject_property_offset() / kTaggedSize; 62 if (!is_inobject()) { 63 result += InObjectPropertyBits::decode(bit_field_); 64 } 65 return result; 66 } 67 GetFieldAccessStubKey()68 int GetFieldAccessStubKey() const { 69 return bit_field_ & 70 (IsInObjectBits::kMask | EncodingBits::kMask | OffsetBits::kMask); 71 } 72 73 bool operator==(FieldIndex const& other) const { 74 return bit_field_ == other.bit_field_; 75 } 76 bool operator!=(FieldIndex const& other) const { return !(*this == other); } 77 78 private: FieldIndex(bool is_inobject,int offset,Encoding encoding,int inobject_properties,int first_inobject_property_offset)79 FieldIndex(bool is_inobject, int offset, Encoding encoding, 80 int inobject_properties, int first_inobject_property_offset) { 81 DCHECK(IsAligned(first_inobject_property_offset, kTaggedSize)); 82 bit_field_ = IsInObjectBits::encode(is_inobject) | 83 EncodingBits::encode(encoding) | 84 FirstInobjectPropertyOffsetBits::encode( 85 first_inobject_property_offset) | 86 OffsetBits::encode(offset) | 87 InObjectPropertyBits::encode(inobject_properties); 88 } 89 FieldEncoding(Representation representation)90 static Encoding FieldEncoding(Representation representation) { 91 switch (representation.kind()) { 92 case Representation::kNone: 93 case Representation::kSmi: 94 case Representation::kHeapObject: 95 case Representation::kTagged: 96 return kTagged; 97 case Representation::kDouble: 98 return kDouble; 99 default: 100 break; 101 } 102 PrintF("%s\n", representation.Mnemonic()); 103 UNREACHABLE(); 104 return kTagged; 105 } 106 first_inobject_property_offset()107 int first_inobject_property_offset() const { 108 return FirstInobjectPropertyOffsetBits::decode(bit_field_); 109 } 110 111 static const int kOffsetBitsSize = 112 (kDescriptorIndexBitCount + 1 + kTaggedSizeLog2); 113 114 // Index from beginning of object. 115 using OffsetBits = base::BitField64<int, 0, kOffsetBitsSize>; 116 using IsInObjectBits = OffsetBits::Next<bool, 1>; 117 using EncodingBits = IsInObjectBits::Next<Encoding, 2>; 118 // Number of inobject properties. 119 using InObjectPropertyBits = 120 EncodingBits::Next<int, kDescriptorIndexBitCount>; 121 // Offset of first inobject property from beginning of object. 122 using FirstInobjectPropertyOffsetBits = 123 InObjectPropertyBits::Next<int, kFirstInobjectPropertyOffsetBitCount>; 124 STATIC_ASSERT(FirstInobjectPropertyOffsetBits::kLastUsedBit < 64); 125 126 uint64_t bit_field_; 127 }; 128 129 } // namespace internal 130 } // namespace v8 131 132 #endif // V8_OBJECTS_FIELD_INDEX_H_ 133