1 | // Copyright 2017 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_JS_ARRAY_H_ |
6 | #define V8_OBJECTS_JS_ARRAY_H_ |
7 | |
8 | #include "src/objects/allocation-site.h" |
9 | #include "src/objects/fixed-array.h" |
10 | #include "src/objects/js-objects.h" |
11 | #include "torque-generated/class-definitions-from-dsl.h" |
12 | |
13 | // Has to be the last include (doesn't have include guards): |
14 | #include "src/objects/object-macros.h" |
15 | |
16 | namespace v8 { |
17 | namespace internal { |
18 | |
19 | // The JSArray describes JavaScript Arrays |
20 | // Such an array can be in one of two modes: |
21 | // - fast, backing storage is a FixedArray and length <= elements.length(); |
22 | // Please note: push and pop can be used to grow and shrink the array. |
23 | // - slow, backing storage is a HashTable with numbers as keys. |
24 | class JSArray : public JSObject { |
25 | public: |
26 | // [length]: The length property. |
27 | DECL_ACCESSORS(length, Object) |
28 | |
29 | // Overload the length setter to skip write barrier when the length |
30 | // is set to a smi. This matches the set function on FixedArray. |
31 | inline void set_length(Smi length); |
32 | |
33 | static bool HasReadOnlyLength(Handle<JSArray> array); |
34 | static bool WouldChangeReadOnlyLength(Handle<JSArray> array, uint32_t index); |
35 | |
36 | // Initialize the array with the given capacity. The function may |
37 | // fail due to out-of-memory situations, but only if the requested |
38 | // capacity is non-zero. |
39 | V8_EXPORT_PRIVATE static void Initialize(Handle<JSArray> array, int capacity, |
40 | int length = 0); |
41 | |
42 | // If the JSArray has fast elements, and new_length would result in |
43 | // normalization, returns true. |
44 | bool SetLengthWouldNormalize(uint32_t new_length); |
45 | static inline bool SetLengthWouldNormalize(Heap* heap, uint32_t new_length); |
46 | |
47 | // Initializes the array to a certain length. |
48 | inline bool AllowsSetLength(); |
49 | |
50 | V8_EXPORT_PRIVATE static void SetLength(Handle<JSArray> array, |
51 | uint32_t length); |
52 | |
53 | // Set the content of the array to the content of storage. |
54 | static inline void SetContent(Handle<JSArray> array, |
55 | Handle<FixedArrayBase> storage); |
56 | |
57 | // ES6 9.4.2.1 |
58 | V8_WARN_UNUSED_RESULT static Maybe<bool> DefineOwnProperty( |
59 | Isolate* isolate, Handle<JSArray> o, Handle<Object> name, |
60 | PropertyDescriptor* desc, Maybe<ShouldThrow> should_throw); |
61 | |
62 | static bool AnythingToArrayLength(Isolate* isolate, |
63 | Handle<Object> length_object, |
64 | uint32_t* output); |
65 | V8_WARN_UNUSED_RESULT static Maybe<bool> ArraySetLength( |
66 | Isolate* isolate, Handle<JSArray> a, PropertyDescriptor* desc, |
67 | Maybe<ShouldThrow> should_throw); |
68 | |
69 | // Support for Array.prototype.join(). |
70 | // Writes a fixed array of strings and separators to a single destination |
71 | // string. This helpers assumes the fixed array encodes separators in two |
72 | // ways: |
73 | // 1) Explicitly with a smi, whos value represents the number of repeated |
74 | // separators. |
75 | // 2) Implicitly between two consecutive strings a single separator. |
76 | // |
77 | // Here are some input/output examples given the separator string is ',': |
78 | // |
79 | // [1, 'hello', 2, 'world', 1] => ',hello,,world,' |
80 | // ['hello', 'world'] => 'hello,world' |
81 | // |
82 | // To avoid any allocations, this helper assumes the destination string is the |
83 | // exact length necessary to write the strings and separators from the fixed |
84 | // array. |
85 | // Since this is called via ExternalReferences, it uses raw Address values: |
86 | // - {raw_fixed_array} is a tagged FixedArray pointer. |
87 | // - {raw_separator} and {raw_dest} are tagged String pointers. |
88 | // - Returns a tagged String pointer. |
89 | static Address ArrayJoinConcatToSequentialString(Isolate* isolate, |
90 | Address raw_fixed_array, |
91 | intptr_t length, |
92 | Address raw_separator, |
93 | Address raw_dest); |
94 | |
95 | // Checks whether the Array has the current realm's Array.prototype as its |
96 | // prototype. This function is best-effort and only gives a conservative |
97 | // approximation, erring on the side of false, in particular with respect |
98 | // to Proxies and objects with a hidden prototype. |
99 | inline bool HasArrayPrototype(Isolate* isolate); |
100 | |
101 | DECL_CAST(JSArray) |
102 | |
103 | // Dispatched behavior. |
104 | DECL_PRINTER(JSArray) |
105 | DECL_VERIFIER(JSArray) |
106 | |
107 | // Number of element slots to pre-allocate for an empty array. |
108 | static const int kPreallocatedArrayElements = 4; |
109 | |
110 | DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, |
111 | TORQUE_GENERATED_JSARRAY_FIELDS) |
112 | |
113 | static const int kLengthDescriptorIndex = 0; |
114 | |
115 | // Max. number of elements being copied in Array builtins. |
116 | static const int kMaxCopyElements = 100; |
117 | |
118 | // This constant is somewhat arbitrary. Any large enough value would work. |
119 | static const uint32_t kMaxFastArrayLength = 32 * 1024 * 1024; |
120 | |
121 | // Min. stack size for detecting an Array.prototype.join() call cycle. |
122 | static const uint32_t kMinJoinStackSize = 2; |
123 | |
124 | static const int kInitialMaxFastElementArray = |
125 | (kMaxRegularHeapObjectSize - FixedArray::kHeaderSize - kSize - |
126 | AllocationMemento::kSize) >> |
127 | kDoubleSizeLog2; |
128 | |
129 | // Valid array indices range from +0 <= i < 2^32 - 1 (kMaxUInt32). |
130 | static const uint32_t kMaxArrayIndex = kMaxUInt32 - 1; |
131 | |
132 | OBJECT_CONSTRUCTORS(JSArray, JSObject); |
133 | }; |
134 | |
135 | Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context, |
136 | Handle<Map> initial_map); |
137 | |
138 | // The JSArrayIterator describes JavaScript Array Iterators Objects, as |
139 | // defined in ES section #sec-array-iterator-objects. |
140 | class JSArrayIterator : public JSObject { |
141 | public: |
142 | DECL_PRINTER(JSArrayIterator) |
143 | DECL_VERIFIER(JSArrayIterator) |
144 | |
145 | DECL_CAST(JSArrayIterator) |
146 | |
147 | // [iterated_object]: the [[IteratedObject]] inobject property. |
148 | DECL_ACCESSORS(iterated_object, Object) |
149 | |
150 | // [next_index]: The [[ArrayIteratorNextIndex]] inobject property. |
151 | // The next_index is always a positive integer, and it points to |
152 | // the next index that is to be returned by this iterator. It's |
153 | // possible range is fixed depending on the [[iterated_object]]: |
154 | // |
155 | // 1. For JSArray's the next_index is always in Unsigned32 |
156 | // range, and when the iterator reaches the end it's set |
157 | // to kMaxUInt32 to indicate that this iterator should |
158 | // never produce values anymore even if the "length" |
159 | // property of the JSArray changes at some later point. |
160 | // 2. For JSTypedArray's the next_index is always in |
161 | // UnsignedSmall range, and when the iterator terminates |
162 | // it's set to Smi::kMaxValue. |
163 | // 3. For all other JSReceiver's it's always between 0 and |
164 | // kMaxSafeInteger, and the latter value is used to mark |
165 | // termination. |
166 | // |
167 | // It's important that for 1. and 2. the value fits into the |
168 | // Unsigned32 range (UnsignedSmall is a subset of Unsigned32), |
169 | // since we use this knowledge in the fast-path for the array |
170 | // iterator next calls in TurboFan (in the JSCallReducer) to |
171 | // keep the index in Word32 representation. This invariant is |
172 | // checked in JSArrayIterator::JSArrayIteratorVerify(). |
173 | DECL_ACCESSORS(next_index, Object) |
174 | |
175 | // [kind]: the [[ArrayIterationKind]] inobject property. |
176 | inline IterationKind kind() const; |
177 | inline void set_kind(IterationKind kind); |
178 | |
179 | DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, |
180 | TORQUE_GENERATED_JSARRAY_ITERATOR_FIELDS) |
181 | |
182 | OBJECT_CONSTRUCTORS(JSArrayIterator, JSObject); |
183 | }; |
184 | |
185 | } // namespace internal |
186 | } // namespace v8 |
187 | |
188 | #include "src/objects/object-macros-undef.h" |
189 | |
190 | #endif // V8_OBJECTS_JS_ARRAY_H_ |
191 | |