• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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