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