• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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_IC_HANDLER_CONFIGURATION_H_
6 #define V8_IC_HANDLER_CONFIGURATION_H_
7 
8 #include "src/elements-kind.h"
9 #include "src/field-index.h"
10 #include "src/globals.h"
11 #include "src/utils.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 // A set of bit fields representing Smi handlers for loads.
17 class LoadHandler {
18  public:
19   enum Kind { kForElements, kForFields, kForConstants, kForNonExistent };
20   class KindBits : public BitField<Kind, 0, 2> {};
21 
22   // Defines whether access rights check should be done on receiver object.
23   // Applicable to kForFields, kForConstants and kForNonExistent kinds only when
24   // loading value from prototype chain. Ignored when loading from holder.
25   class DoAccessCheckOnReceiverBits
26       : public BitField<bool, KindBits::kNext, 1> {};
27 
28   // Defines whether negative lookup check should be done on receiver object.
29   // Applicable to kForFields, kForConstants and kForNonExistent kinds only when
30   // loading value from prototype chain. Ignored when loading from holder.
31   class DoNegativeLookupOnReceiverBits
32       : public BitField<bool, DoAccessCheckOnReceiverBits::kNext, 1> {};
33 
34   //
35   // Encoding when KindBits contains kForConstants.
36   //
37 
38   class IsAccessorInfoBits
39       : public BitField<bool, DoNegativeLookupOnReceiverBits::kNext, 1> {};
40   // Index of a value entry in the descriptor array.
41   // +2 here is because each descriptor entry occupies 3 slots in array.
42   class DescriptorValueIndexBits
43       : public BitField<unsigned, IsAccessorInfoBits::kNext,
44                         kDescriptorIndexBitCount + 2> {};
45   // Make sure we don't overflow the smi.
46   STATIC_ASSERT(DescriptorValueIndexBits::kNext <= kSmiValueSize);
47 
48   //
49   // Encoding when KindBits contains kForFields.
50   //
51   class IsInobjectBits
52       : public BitField<bool, DoNegativeLookupOnReceiverBits::kNext, 1> {};
53   class IsDoubleBits : public BitField<bool, IsInobjectBits::kNext, 1> {};
54   // +1 here is to cover all possible JSObject header sizes.
55   class FieldOffsetBits
56       : public BitField<unsigned, IsDoubleBits::kNext,
57                         kDescriptorIndexBitCount + 1 + kPointerSizeLog2> {};
58   // Make sure we don't overflow the smi.
59   STATIC_ASSERT(FieldOffsetBits::kNext <= kSmiValueSize);
60 
61   //
62   // Encoding when KindBits contains kForElements.
63   //
64   class IsJsArrayBits : public BitField<bool, KindBits::kNext, 1> {};
65   class ConvertHoleBits : public BitField<bool, IsJsArrayBits::kNext, 1> {};
66   class ElementsKindBits
67       : public BitField<ElementsKind, ConvertHoleBits::kNext, 8> {};
68   // Make sure we don't overflow the smi.
69   STATIC_ASSERT(ElementsKindBits::kNext <= kSmiValueSize);
70 
71   // The layout of an Tuple3 handler representing a load of a field from
72   // prototype when prototype chain checks do not include non-existing lookups
73   // or access checks.
74   static const int kHolderCellOffset = Tuple3::kValue1Offset;
75   static const int kSmiHandlerOffset = Tuple3::kValue2Offset;
76   static const int kValidityCellOffset = Tuple3::kValue3Offset;
77 
78   // The layout of an array handler representing a load of a field from
79   // prototype when prototype chain checks include non-existing lookups and
80   // access checks.
81   static const int kSmiHandlerIndex = 0;
82   static const int kValidityCellIndex = 1;
83   static const int kHolderCellIndex = 2;
84   static const int kFirstPrototypeIndex = 3;
85 
86   // Creates a Smi-handler for loading a field from fast object.
87   static inline Handle<Object> LoadField(Isolate* isolate,
88                                          FieldIndex field_index);
89 
90   // Creates a Smi-handler for loading a constant from fast object.
91   static inline Handle<Object> LoadConstant(Isolate* isolate, int descriptor);
92 
93   // Creates a Smi-handler for loading an Api getter property from fast object.
94   static inline Handle<Object> LoadApiGetter(Isolate* isolate, int descriptor);
95 
96   // Sets DoAccessCheckOnReceiverBits in given Smi-handler. The receiver
97   // check is a part of a prototype chain check.
98   static inline Handle<Object> EnableAccessCheckOnReceiver(
99       Isolate* isolate, Handle<Object> smi_handler);
100 
101   // Sets DoNegativeLookupOnReceiverBits in given Smi-handler. The receiver
102   // check is a part of a prototype chain check.
103   static inline Handle<Object> EnableNegativeLookupOnReceiver(
104       Isolate* isolate, Handle<Object> smi_handler);
105 
106   // Creates a Smi-handler for loading a non-existent property. Works only as
107   // a part of prototype chain check.
108   static inline Handle<Object> LoadNonExistent(
109       Isolate* isolate, bool do_negative_lookup_on_receiver);
110 
111   // Creates a Smi-handler for loading an element.
112   static inline Handle<Object> LoadElement(Isolate* isolate,
113                                            ElementsKind elements_kind,
114                                            bool convert_hole_to_undefined,
115                                            bool is_js_array);
116 };
117 
118 // A set of bit fields representing Smi handlers for stores.
119 class StoreHandler {
120  public:
121   enum Kind {
122     kStoreElement,
123     kStoreField,
124     kStoreConstField,
125     kTransitionToField,
126     // TODO(ishell): remove once constant field tracking is done.
127     kTransitionToConstant = kStoreConstField
128   };
129   class KindBits : public BitField<Kind, 0, 2> {};
130 
131   enum FieldRepresentation { kSmi, kDouble, kHeapObject, kTagged };
132 
133   // Applicable to kStoreField, kTransitionToField and kTransitionToConstant
134   // kinds.
135 
136   // Index of a value entry in the descriptor array.
137   // +2 here is because each descriptor entry occupies 3 slots in array.
138   class DescriptorValueIndexBits
139       : public BitField<unsigned, KindBits::kNext,
140                         kDescriptorIndexBitCount + 2> {};
141   //
142   // Encoding when KindBits contains kTransitionToConstant.
143   //
144 
145   // Make sure we don't overflow the smi.
146   STATIC_ASSERT(DescriptorValueIndexBits::kNext <= kSmiValueSize);
147 
148   //
149   // Encoding when KindBits contains kStoreField or kTransitionToField.
150   //
151   class ExtendStorageBits
152       : public BitField<bool, DescriptorValueIndexBits::kNext, 1> {};
153   class IsInobjectBits : public BitField<bool, ExtendStorageBits::kNext, 1> {};
154   class FieldRepresentationBits
155       : public BitField<FieldRepresentation, IsInobjectBits::kNext, 2> {};
156   // +1 here is to cover all possible JSObject header sizes.
157   class FieldOffsetBits
158       : public BitField<unsigned, FieldRepresentationBits::kNext,
159                         kDescriptorIndexBitCount + 1 + kPointerSizeLog2> {};
160   // Make sure we don't overflow the smi.
161   STATIC_ASSERT(FieldOffsetBits::kNext <= kSmiValueSize);
162 
163   // The layout of an Tuple3 handler representing a transitioning store
164   // when prototype chain checks do not include non-existing lookups or access
165   // checks.
166   static const int kTransitionCellOffset = Tuple3::kValue1Offset;
167   static const int kSmiHandlerOffset = Tuple3::kValue2Offset;
168   static const int kValidityCellOffset = Tuple3::kValue3Offset;
169 
170   // The layout of an array handler representing a transitioning store
171   // when prototype chain checks include non-existing lookups and access checks.
172   static const int kSmiHandlerIndex = 0;
173   static const int kValidityCellIndex = 1;
174   static const int kTransitionCellIndex = 2;
175   static const int kFirstPrototypeIndex = 3;
176 
177   // Creates a Smi-handler for storing a field to fast object.
178   static inline Handle<Object> StoreField(Isolate* isolate, int descriptor,
179                                           FieldIndex field_index,
180                                           PropertyConstness constness,
181                                           Representation representation);
182 
183   // Creates a Smi-handler for transitioning store to a field.
184   static inline Handle<Object> TransitionToField(Isolate* isolate,
185                                                  int descriptor,
186                                                  FieldIndex field_index,
187                                                  Representation representation,
188                                                  bool extend_storage);
189 
190   // Creates a Smi-handler for transitioning store to a constant field (in this
191   // case the only thing that needs to be done is an update of a map).
192   static inline Handle<Object> TransitionToConstant(Isolate* isolate,
193                                                     int descriptor);
194 
195  private:
196   static inline Handle<Object> StoreField(Isolate* isolate, Kind kind,
197                                           int descriptor,
198                                           FieldIndex field_index,
199                                           Representation representation,
200                                           bool extend_storage);
201 };
202 
203 }  // namespace internal
204 }  // namespace v8
205 
206 #endif  // V8_IC_HANDLER_CONFIGURATION_H_
207