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/utils.h" 9 #include "src/property-details.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 V8_FINAL { 21 public: 22 static FieldIndex ForPropertyIndex(Map* map, 23 int index, 24 bool is_double = false); 25 static FieldIndex ForInObjectOffset(int offset, Map* map = NULL); 26 static FieldIndex ForLookupResult(const LookupResult* result); 27 static FieldIndex ForDescriptor(Map* map, int descriptor_index); 28 static FieldIndex ForLoadByFieldIndex(Map* map, int index); 29 static FieldIndex ForKeyedLookupCacheIndex(Map* map, int index); 30 is_inobject()31 bool is_inobject() const { 32 return IsInObjectBits::decode(bit_field_); 33 } 34 is_double()35 bool is_double() const { 36 return IsDoubleBits::decode(bit_field_); 37 } 38 offset()39 int offset() const { 40 return index() * kPointerSize; 41 } 42 index()43 int index() const { 44 return IndexBits::decode(bit_field_); 45 } 46 outobject_array_index()47 int outobject_array_index() const { 48 ASSERT(!is_inobject()); 49 return index() - first_inobject_property_offset() / kPointerSize; 50 } 51 property_index()52 int property_index() const { 53 ASSERT(!IsHiddenField::decode(bit_field_)); 54 int result = index() - first_inobject_property_offset() / kPointerSize; 55 if (!is_inobject()) { 56 result += InObjectPropertyBits::decode(bit_field_); 57 } 58 return result; 59 } 60 GetLoadByFieldIndex()61 int GetLoadByFieldIndex() const { 62 // For efficiency, the LoadByFieldIndex instruction takes an index that is 63 // optimized for quick access. If the property is inline, the index is 64 // positive. If it's out-of-line, the encoded index is -raw_index - 1 to 65 // disambiguate the zero out-of-line index from the zero inobject case. 66 // The index itself is shifted up by one bit, the lower-most bit 67 // signifying if the field is a mutable double box (1) or not (0). 68 int result = index() - first_inobject_property_offset() / kPointerSize; 69 if (!is_inobject()) { 70 result = -result - 1; 71 } 72 result <<= 1; 73 return is_double() ? (result | 1) : result; 74 } 75 76 int GetKeyedLookupCacheIndex() const; 77 GetLoadFieldStubKey()78 int GetLoadFieldStubKey() const { 79 return bit_field_ & 80 (IsInObjectBits::kMask | IsDoubleBits::kMask | IndexBits::kMask); 81 } 82 83 private: 84 FieldIndex(bool is_inobject, int local_index, bool is_double, 85 int inobject_properties, int first_inobject_property_offset, 86 bool is_hidden = false) { 87 ASSERT((first_inobject_property_offset & (kPointerSize - 1)) == 0); 88 bit_field_ = IsInObjectBits::encode(is_inobject) | 89 IsDoubleBits::encode(is_double) | 90 FirstInobjectPropertyOffsetBits::encode(first_inobject_property_offset) | 91 IsHiddenField::encode(is_hidden) | 92 IndexBits::encode(local_index) | 93 InObjectPropertyBits::encode(inobject_properties); 94 } 95 first_inobject_property_offset()96 int first_inobject_property_offset() const { 97 ASSERT(!IsHiddenField::decode(bit_field_)); 98 return FirstInobjectPropertyOffsetBits::decode(bit_field_); 99 } 100 101 static const int kIndexBitsSize = kDescriptorIndexBitCount + 1; 102 103 class IndexBits: public BitField<int, 0, kIndexBitsSize> {}; 104 class IsInObjectBits: public BitField<bool, IndexBits::kNext, 1> {}; 105 class IsDoubleBits: public BitField<bool, IsInObjectBits::kNext, 1> {}; 106 class InObjectPropertyBits: public BitField<int, IsDoubleBits::kNext, 107 kDescriptorIndexBitCount> {}; 108 class FirstInobjectPropertyOffsetBits: 109 public BitField<int, InObjectPropertyBits::kNext, 7> {}; 110 class IsHiddenField: 111 public BitField<bool, FirstInobjectPropertyOffsetBits::kNext, 1> {}; 112 STATIC_ASSERT(IsHiddenField::kNext <= 32); 113 114 int bit_field_; 115 }; 116 117 } } // namespace v8::internal 118 119 #endif 120