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
16namespace v8 {
17namespace 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.
24class 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
135Handle<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.
140class 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