• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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_ELEMENTS_H_
6 #define V8_OBJECTS_ELEMENTS_H_
7 
8 #include "src/builtins/builtins-utils.h"
9 #include "src/objects/elements-kind.h"
10 #include "src/objects/internal-index.h"
11 #include "src/objects/keys.h"
12 #include "src/objects/objects.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 class JSTypedArray;
18 
19 // Abstract base class for handles that can operate on objects with differing
20 // ElementsKinds.
21 class ElementsAccessor {
22  public:
23   ElementsAccessor() = default;
24   virtual ~ElementsAccessor() = default;
25   ElementsAccessor(const ElementsAccessor&) = delete;
26   ElementsAccessor& operator=(const ElementsAccessor&) = delete;
27 
28   // Returns a shared ElementsAccessor for the specified ElementsKind.
ForKind(ElementsKind elements_kind)29   static ElementsAccessor* ForKind(ElementsKind elements_kind) {
30     DCHECK_LT(static_cast<int>(elements_kind), kElementsKindCount);
31     return elements_accessors_[elements_kind];
32   }
33 
34   // Checks the elements of an object for consistency, asserting when a problem
35   // is found.
36   virtual void Validate(JSObject obj) = 0;
37 
38   // Returns true if a holder contains an element with the specified index
39   // without iterating up the prototype chain. The first version takes the
40   // backing store to use for the check, which must be compatible with the
41   // ElementsKind of the ElementsAccessor; the second version uses
42   // holder->elements() as the backing store. If a |filter| is specified,
43   // the PropertyAttributes of the element at the given index are compared
44   // to the given |filter|. If they match/overlap, the given index is ignored.
45   // Note that only Dictionary elements have custom
46   // PropertyAttributes associated, hence the |filter| argument is ignored for
47   // all but DICTIONARY_ELEMENTS and SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
48   virtual bool HasElement(JSObject holder, uint32_t index,
49                           FixedArrayBase backing_store,
50                           PropertyFilter filter = ALL_PROPERTIES) = 0;
51 
52   inline bool HasElement(JSObject holder, uint32_t index,
53                          PropertyFilter filter = ALL_PROPERTIES);
54 
55   // Note: this is currently not implemented for string wrapper and
56   // typed array elements.
57   virtual bool HasEntry(JSObject holder, InternalIndex entry) = 0;
58 
59   virtual Handle<Object> Get(Handle<JSObject> holder, InternalIndex entry) = 0;
60 
61   virtual bool HasAccessors(JSObject holder) = 0;
62   virtual size_t NumberOfElements(JSObject holder) = 0;
63 
64   // Modifies the length data property as specified for JSArrays and resizes the
65   // underlying backing store accordingly. The method honors the semantics of
66   // changing array sizes as defined in EcmaScript 5.1 15.4.5.2, i.e. array that
67   // have non-deletable elements can only be shrunk to the size of highest
68   // element that is non-deletable.
69   V8_WARN_UNUSED_RESULT virtual Maybe<bool> SetLength(Handle<JSArray> holder,
70                                                       uint32_t new_length) = 0;
71 
72   // Copy all indices that have elements from |object| into the given
73   // KeyAccumulator. For Dictionary-based element-kinds we filter out elements
74   // whose PropertyAttribute match |filter|.
75   V8_WARN_UNUSED_RESULT virtual ExceptionStatus CollectElementIndices(
76       Handle<JSObject> object, Handle<FixedArrayBase> backing_store,
77       KeyAccumulator* keys) = 0;
78 
79   V8_WARN_UNUSED_RESULT inline ExceptionStatus CollectElementIndices(
80       Handle<JSObject> object, KeyAccumulator* keys);
81 
82   virtual Maybe<bool> CollectValuesOrEntries(
83       Isolate* isolate, Handle<JSObject> object,
84       Handle<FixedArray> values_or_entries, bool get_entries, int* nof_items,
85       PropertyFilter filter = ALL_PROPERTIES) = 0;
86 
87   virtual MaybeHandle<FixedArray> PrependElementIndices(
88       Handle<JSObject> object, Handle<FixedArrayBase> backing_store,
89       Handle<FixedArray> keys, GetKeysConversion convert,
90       PropertyFilter filter = ALL_PROPERTIES) = 0;
91 
92   inline MaybeHandle<FixedArray> PrependElementIndices(
93       Handle<JSObject> object, Handle<FixedArray> keys,
94       GetKeysConversion convert, PropertyFilter filter = ALL_PROPERTIES);
95 
96   V8_WARN_UNUSED_RESULT virtual ExceptionStatus AddElementsToKeyAccumulator(
97       Handle<JSObject> receiver, KeyAccumulator* accumulator,
98       AddKeyConversion convert) = 0;
99 
100   V8_WARN_UNUSED_RESULT virtual Maybe<bool> TransitionElementsKind(
101       Handle<JSObject> object, Handle<Map> map) = 0;
102   V8_WARN_UNUSED_RESULT virtual Maybe<bool> GrowCapacityAndConvert(
103       Handle<JSObject> object, uint32_t capacity) = 0;
104   // Unlike GrowCapacityAndConvert do not attempt to convert the backing store
105   // and simply return false in this case.
106   V8_WARN_UNUSED_RESULT virtual Maybe<bool> GrowCapacity(
107       Handle<JSObject> object, uint32_t index) = 0;
108 
109   static void InitializeOncePerProcess();
110   static void TearDown();
111 
112   virtual void Set(Handle<JSObject> holder, InternalIndex entry,
113                    Object value) = 0;
114 
115   V8_WARN_UNUSED_RESULT virtual Maybe<bool> Add(Handle<JSObject> object,
116                                                 uint32_t index,
117                                                 Handle<Object> value,
118                                                 PropertyAttributes attributes,
119                                                 uint32_t new_capacity) = 0;
120 
121   static Handle<JSArray> Concat(Isolate* isolate, BuiltinArguments* args,
122                                 uint32_t concat_size, uint32_t result_length);
123 
124   V8_WARN_UNUSED_RESULT virtual Maybe<uint32_t> Push(Handle<JSArray> receiver,
125                                                      BuiltinArguments* args,
126                                                      uint32_t push_size) = 0;
127 
128   V8_WARN_UNUSED_RESULT virtual Maybe<uint32_t> Unshift(
129       Handle<JSArray> receiver, BuiltinArguments* args,
130       uint32_t unshift_size) = 0;
131 
132   V8_WARN_UNUSED_RESULT virtual MaybeHandle<Object> Pop(
133       Handle<JSArray> receiver) = 0;
134 
135   V8_WARN_UNUSED_RESULT virtual MaybeHandle<Object> Shift(
136       Handle<JSArray> receiver) = 0;
137 
138   virtual Handle<NumberDictionary> Normalize(Handle<JSObject> object) = 0;
139 
140   virtual size_t GetCapacity(JSObject holder, FixedArrayBase backing_store) = 0;
141 
142   V8_WARN_UNUSED_RESULT virtual MaybeHandle<Object> Fill(
143       Handle<JSObject> receiver, Handle<Object> obj_value, size_t start,
144       size_t end) = 0;
145 
146   // Check an Object's own elements for an element (using SameValueZero
147   // semantics)
148   virtual Maybe<bool> IncludesValue(Isolate* isolate, Handle<JSObject> receiver,
149                                     Handle<Object> value, size_t start,
150                                     size_t length) = 0;
151 
152   // Check an Object's own elements for the index of an element (using SameValue
153   // semantics)
154   virtual Maybe<int64_t> IndexOfValue(Isolate* isolate,
155                                       Handle<JSObject> receiver,
156                                       Handle<Object> value, size_t start,
157                                       size_t length) = 0;
158 
159   virtual Maybe<int64_t> LastIndexOfValue(Handle<JSObject> receiver,
160                                           Handle<Object> value,
161                                           size_t start) = 0;
162 
163   virtual void Reverse(JSObject receiver) = 0;
164 
165   virtual void CopyElements(Isolate* isolate, Handle<FixedArrayBase> source,
166                             ElementsKind source_kind,
167                             Handle<FixedArrayBase> destination, int size) = 0;
168 
169   virtual Object CopyElements(Handle<Object> source,
170                               Handle<JSObject> destination, size_t length,
171                               size_t offset) = 0;
172 
173   virtual Handle<FixedArray> CreateListFromArrayLike(Isolate* isolate,
174                                                      Handle<JSObject> object,
175                                                      uint32_t length) = 0;
176 
177   virtual void CopyTypedArrayElementsSlice(JSTypedArray source,
178                                            JSTypedArray destination,
179                                            size_t start, size_t end) = 0;
180 
181  protected:
182   friend class LookupIterator;
183 
184   // Element handlers distinguish between entries and indices when they
185   // manipulate elements. Entries refer to elements in terms of their location
186   // in the underlying storage's backing store representation, and are between 0
187   // and GetCapacity. Indices refer to elements in terms of the value that would
188   // be specified in JavaScript to access the element. In most implementations,
189   // indices are equivalent to entries. In the NumberDictionary
190   // ElementsAccessor, entries are mapped to an index using the KeyAt method on
191   // the NumberDictionary.
192   virtual InternalIndex GetEntryForIndex(Isolate* isolate, JSObject holder,
193                                          FixedArrayBase backing_store,
194                                          size_t index) = 0;
195 
196   virtual PropertyDetails GetDetails(JSObject holder, InternalIndex entry) = 0;
197   virtual void Reconfigure(Handle<JSObject> object,
198                            Handle<FixedArrayBase> backing_store,
199                            InternalIndex entry, Handle<Object> value,
200                            PropertyAttributes attributes) = 0;
201 
202   // Deletes an element in an object.
203   virtual void Delete(Handle<JSObject> holder, InternalIndex entry) = 0;
204 
205   // NOTE: this method violates the handlified function signature convention:
206   // raw pointer parameter |source_holder| in the function that allocates.
207   // This is done intentionally to avoid ArrayConcat() builtin performance
208   // degradation.
209   virtual void CopyElements(JSObject source_holder, uint32_t source_start,
210                             ElementsKind source_kind,
211                             Handle<FixedArrayBase> destination,
212                             uint32_t destination_start, int copy_size) = 0;
213 
214  private:
215   V8_EXPORT_PRIVATE static ElementsAccessor** elements_accessors_;
216 };
217 
218 V8_WARN_UNUSED_RESULT MaybeHandle<Object> ArrayConstructInitializeElements(
219     Handle<JSArray> array, JavaScriptArguments* args);
220 
221 // Called directly from CSA.
222 // {raw_context}: Context pointer.
223 // {raw_source}: JSArray pointer.
224 // {raw_destination}: JSTypedArray pointer.
225 void CopyFastNumberJSArrayElementsToTypedArray(Address raw_context,
226                                                Address raw_source,
227                                                Address raw_destination,
228                                                uintptr_t length,
229                                                uintptr_t offset);
230 // {raw_source}, {raw_destination}: JSTypedArray pointers.
231 void CopyTypedArrayElementsToTypedArray(Address raw_source,
232                                         Address raw_destination,
233                                         uintptr_t length, uintptr_t offset);
234 // {raw_source}, {raw_destination}: JSTypedArray pointers.
235 void CopyTypedArrayElementsSlice(Address raw_source, Address raw_destination,
236                                  uintptr_t start, uintptr_t end);
237 
238 }  // namespace internal
239 }  // namespace v8
240 
241 #endif  // V8_OBJECTS_ELEMENTS_H_
242