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
13namespace v8 {
14namespace internal {
15
16// A set of bit fields representing Smi handlers for loads.
17class 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.
119class 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