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(IsolateRoot isolate, 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 45 // Zero-indexed from beginning of the object. index()46 int index() const { 47 DCHECK(IsAligned(offset(), kTaggedSize)); 48 return offset() / kTaggedSize; 49 } 50 outobject_array_index()51 int outobject_array_index() const { 52 DCHECK(!is_inobject()); 53 return index() - first_inobject_property_offset() / kTaggedSize; 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 int result = index() - first_inobject_property_offset() / kTaggedSize; 60 if (!is_inobject()) { 61 result += InObjectPropertyBits::decode(bit_field_); 62 } 63 return result; 64 } 65 GetFieldAccessStubKey()66 int GetFieldAccessStubKey() const { 67 return bit_field_ & 68 (IsInObjectBits::kMask | EncodingBits::kMask | OffsetBits::kMask); 69 } 70 71 bool operator==(FieldIndex const& other) const { 72 return bit_field_ == other.bit_field_; 73 } 74 bool operator!=(FieldIndex const& other) const { return !(*this == other); } 75 76 private: FieldIndex(bool is_inobject,int offset,Encoding encoding,int inobject_properties,int first_inobject_property_offset)77 FieldIndex(bool is_inobject, int offset, Encoding encoding, 78 int inobject_properties, int first_inobject_property_offset) { 79 DCHECK(IsAligned(first_inobject_property_offset, kTaggedSize)); 80 bit_field_ = IsInObjectBits::encode(is_inobject) | 81 EncodingBits::encode(encoding) | 82 FirstInobjectPropertyOffsetBits::encode( 83 first_inobject_property_offset) | 84 OffsetBits::encode(offset) | 85 InObjectPropertyBits::encode(inobject_properties); 86 } 87 FieldEncoding(Representation representation)88 static Encoding FieldEncoding(Representation representation) { 89 switch (representation.kind()) { 90 case Representation::kNone: 91 case Representation::kSmi: 92 case Representation::kHeapObject: 93 case Representation::kTagged: 94 return kTagged; 95 case Representation::kDouble: 96 return kDouble; 97 default: 98 break; 99 } 100 PrintF("%s\n", representation.Mnemonic()); 101 UNREACHABLE(); 102 return kTagged; 103 } 104 first_inobject_property_offset()105 int first_inobject_property_offset() const { 106 return FirstInobjectPropertyOffsetBits::decode(bit_field_); 107 } 108 109 static const int kOffsetBitsSize = 110 (kDescriptorIndexBitCount + 1 + kTaggedSizeLog2); 111 112 // Index from beginning of object. 113 using OffsetBits = base::BitField64<int, 0, kOffsetBitsSize>; 114 using IsInObjectBits = OffsetBits::Next<bool, 1>; 115 using EncodingBits = IsInObjectBits::Next<Encoding, 2>; 116 // Number of inobject properties. 117 using InObjectPropertyBits = 118 EncodingBits::Next<int, kDescriptorIndexBitCount>; 119 // Offset of first inobject property from beginning of object. 120 using FirstInobjectPropertyOffsetBits = 121 InObjectPropertyBits::Next<int, kFirstInobjectPropertyOffsetBitCount>; 122 STATIC_ASSERT(FirstInobjectPropertyOffsetBits::kLastUsedBit < 64); 123 124 uint64_t bit_field_; 125 }; 126 127 } // namespace internal 128 } // namespace v8 129 130 #endif // V8_OBJECTS_FIELD_INDEX_H_ 131