• 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_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