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