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_FIELD_INDEX_H_ 6 #define V8_FIELD_INDEX_H_ 7 8 #include "src/property-details.h" 9 #include "src/utils.h" 10 11 namespace v8 { 12 namespace internal { 13 14 class Map; 15 16 // Wrapper class to hold a field index, usually but not necessarily generated 17 // from a property index. When available, the wrapper class captures additional 18 // information to allow the field index to be translated back into the property 19 // index it was originally generated from. 20 class FieldIndex final { 21 public: 22 enum Encoding { kTagged, kDouble, kWord32 }; 23 FieldIndex()24 FieldIndex() : bit_field_(0) {} 25 26 static FieldIndex ForPropertyIndex( 27 const Map* map, int index, 28 Representation representation = Representation::Tagged()); 29 static FieldIndex ForInObjectOffset(int offset, Encoding encoding, 30 const Map* map = nullptr); 31 static FieldIndex ForDescriptor(const Map* map, int descriptor_index); 32 33 int GetLoadByFieldIndex() const; 34 is_inobject()35 bool is_inobject() const { 36 return IsInObjectBits::decode(bit_field_); 37 } 38 is_hidden_field()39 bool is_hidden_field() const { return IsHiddenField::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 45 // Zero-indexed from beginning of the object. index()46 int index() const { 47 DCHECK_EQ(0, offset() % kPointerSize); 48 return offset() / kPointerSize; 49 } 50 outobject_array_index()51 int outobject_array_index() const { 52 DCHECK(!is_inobject()); 53 return index() - first_inobject_property_offset() / kPointerSize; 54 } 55 56 // Zero-based from the first inobject property. Overflows to out-of-object 57 // properties. property_index()58 int property_index() const { 59 DCHECK(!is_hidden_field()); 60 int result = index() - first_inobject_property_offset() / kPointerSize; 61 if (!is_inobject()) { 62 result += InObjectPropertyBits::decode(bit_field_); 63 } 64 return result; 65 } 66 GetFieldAccessStubKey()67 int GetFieldAccessStubKey() const { 68 return bit_field_ & 69 (IsInObjectBits::kMask | EncodingBits::kMask | OffsetBits::kMask); 70 } 71 72 bool operator==(FieldIndex const& other) const { 73 return bit_field_ == other.bit_field_; 74 } 75 bool operator!=(FieldIndex const& other) const { return !(*this == other); } 76 77 private: 78 FieldIndex(bool is_inobject, int offset, Encoding encoding, 79 int inobject_properties, int first_inobject_property_offset, 80 bool is_hidden = false) { 81 DCHECK_EQ(first_inobject_property_offset & (kPointerSize - 1), 0); 82 bit_field_ = IsInObjectBits::encode(is_inobject) | 83 EncodingBits::encode(encoding) | 84 FirstInobjectPropertyOffsetBits::encode( 85 first_inobject_property_offset) | 86 IsHiddenField::encode(is_hidden) | 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 DCHECK(!is_hidden_field()); 109 return FirstInobjectPropertyOffsetBits::decode(bit_field_); 110 } 111 112 static const int kOffsetBitsSize = 113 (kDescriptorIndexBitCount + 1 + kPointerSizeLog2); 114 115 // Index from beginning of object. 116 class OffsetBits : public BitField64<int, 0, kOffsetBitsSize> {}; 117 class IsInObjectBits : public BitField64<bool, OffsetBits::kNext, 1> {}; 118 class EncodingBits : public BitField64<Encoding, IsInObjectBits::kNext, 2> {}; 119 // Number of inobject properties. 120 class InObjectPropertyBits 121 : public BitField64<int, EncodingBits::kNext, kDescriptorIndexBitCount> { 122 }; 123 // Offset of first inobject property from beginning of object. 124 class FirstInobjectPropertyOffsetBits 125 : public BitField64<int, InObjectPropertyBits::kNext, 126 kFirstInobjectPropertyOffsetBitCount> {}; 127 class IsHiddenField 128 : public BitField64<bool, FirstInobjectPropertyOffsetBits::kNext, 1> {}; 129 STATIC_ASSERT(IsHiddenField::kNext <= 64); 130 131 uint64_t bit_field_; 132 }; 133 134 } // namespace internal 135 } // namespace v8 136 137 #endif // V8_FIELD_INDEX_H_ 138