1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 /* JS Array interface. */
8
9 #ifndef jsarray_h
10 #define jsarray_h
11
12 #include "jsobj.h"
13 #include "jspubtd.h"
14
15 #include "vm/ArrayObject.h"
16
17 namespace js {
18 /* 2^32-2, inclusive */
19 const uint32_t MAX_ARRAY_INDEX = 4294967294u;
20
21 inline bool
IdIsIndex(jsid id,uint32_t * indexp)22 IdIsIndex(jsid id, uint32_t* indexp)
23 {
24 if (JSID_IS_INT(id)) {
25 int32_t i = JSID_TO_INT(id);
26 MOZ_ASSERT(i >= 0);
27 *indexp = (uint32_t)i;
28 return true;
29 }
30
31 if (MOZ_UNLIKELY(!JSID_IS_STRING(id)))
32 return false;
33
34 return js::StringIsArrayIndex(JSID_TO_ATOM(id), indexp);
35 }
36
37 extern JSObject*
38 InitArrayClass(JSContext* cx, js::HandleObject obj);
39
40 // The methods below only create dense boxed arrays.
41
42 /* Create a dense array with no capacity allocated, length set to 0. */
43 extern ArrayObject * JS_FASTCALL
44 NewDenseEmptyArray(JSContext* cx, HandleObject proto = nullptr,
45 NewObjectKind newKind = GenericObject);
46
47 /*
48 * Create a dense array with a set length, but without allocating space for the
49 * contents. This is useful, e.g., when accepting length from the user.
50 */
51 extern ArrayObject * JS_FASTCALL
52 NewDenseUnallocatedArray(ExclusiveContext* cx, uint32_t length, HandleObject proto = nullptr,
53 NewObjectKind newKind = GenericObject);
54
55 /*
56 * Create a dense array with length and capacity == |length|, initialized length set to 0,
57 * but with only |EagerAllocationMaxLength| elements allocated.
58 */
59 extern ArrayObject * JS_FASTCALL
60 NewDensePartlyAllocatedArray(ExclusiveContext* cx, uint32_t length, HandleObject proto = nullptr,
61 NewObjectKind newKind = GenericObject);
62
63 /* Create a dense array with length and capacity == 'length', initialized length set to 0. */
64 extern ArrayObject * JS_FASTCALL
65 NewDenseFullyAllocatedArray(ExclusiveContext* cx, uint32_t length, HandleObject proto = nullptr,
66 NewObjectKind newKind = GenericObject);
67
68 /* Create a dense array from the given array values, which must be rooted */
69 extern ArrayObject*
70 NewDenseCopiedArray(ExclusiveContext* cx, uint32_t length, const Value* values,
71 HandleObject proto = nullptr, NewObjectKind newKind = GenericObject);
72
73 /* Create a dense array based on templateObject with the given length. */
74 extern ArrayObject*
75 NewDenseFullyAllocatedArrayWithTemplate(JSContext* cx, uint32_t length, JSObject* templateObject);
76
77 /* Create a dense array with the same copy-on-write elements as another object. */
78 extern JSObject*
79 NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc::InitialHeap heap);
80
81 // The methods below can create either boxed or unboxed arrays.
82
83 extern JSObject*
84 NewFullyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
85 NewObjectKind newKind = GenericObject, bool forceAnalyze = false);
86
87 extern JSObject*
88 NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length);
89
90 extern JSObject*
91 NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
92 NewObjectKind newKind = GenericObject,
93 bool forceAnalyze = false);
94
95 extern JSObject*
96 NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length);
97
98 extern JSObject*
99 NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
100 NewObjectKind newKind = GenericObject,
101 bool forceAnalyze = false);
102
103 extern JSObject*
104 NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, HandleObject proto);
105
106 enum class ShouldUpdateTypes
107 {
108 Update,
109 DontUpdate
110 };
111
112 extern JSObject*
113 NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group,
114 const Value* vp, size_t length,
115 NewObjectKind newKind = GenericObject,
116 ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update);
117
118 extern JSObject*
119 NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_t length,
120 HandleObject proto = nullptr);
121
122 /*
123 * Determines whether a write to the given element on |obj| should fail because
124 * |obj| is an Array with a non-writable length, and writing that element would
125 * increase the length of the array.
126 */
127 extern bool
128 WouldDefinePastNonwritableLength(HandleNativeObject obj, uint32_t index);
129
130 /*
131 * Canonicalize |vp| to a uint32_t value potentially suitable for use as an
132 * array length.
133 */
134 extern bool
135 CanonicalizeArrayLengthValue(JSContext* cx, HandleValue v, uint32_t* canonicalized);
136
137 extern bool
138 GetLengthProperty(JSContext* cx, HandleObject obj, uint32_t* lengthp);
139
140 extern bool
141 SetLengthProperty(JSContext* cx, HandleObject obj, double length);
142
143 extern bool
144 ObjectMayHaveExtraIndexedProperties(JSObject* obj);
145
146 /*
147 * Copy 'length' elements from aobj to vp.
148 *
149 * This function assumes 'length' is effectively the result of calling
150 * GetLengthProperty on aobj. vp must point to rooted memory.
151 */
152 extern bool
153 GetElements(JSContext* cx, HandleObject aobj, uint32_t length, js::Value* vp);
154
155 /* Natives exposed for optimization by the interpreter and JITs. */
156
157 extern bool
158 array_sort(JSContext* cx, unsigned argc, js::Value* vp);
159
160 extern bool
161 array_push(JSContext* cx, unsigned argc, js::Value* vp);
162
163 extern bool
164 array_pop(JSContext* cx, unsigned argc, js::Value* vp);
165
166 extern bool
167 array_splice_impl(JSContext* cx, unsigned argc, js::Value* vp, bool pop);
168
169 extern bool
170 array_concat(JSContext* cx, unsigned argc, js::Value* vp);
171
172 template <bool Locale>
173 JSString*
174 ArrayJoin(JSContext* cx, HandleObject obj, HandleLinearString sepstr, uint32_t length);
175
176 extern bool
177 array_concat_dense(JSContext* cx, HandleObject arr1, HandleObject arr2,
178 HandleObject result);
179
180 extern bool
181 array_join(JSContext* cx, unsigned argc, js::Value* vp);
182
183 extern JSString*
184 array_join_impl(JSContext* cx, HandleValue array, HandleString sep);
185
186 extern void
187 ArrayShiftMoveElements(JSObject* obj);
188
189 extern bool
190 array_shift(JSContext* cx, unsigned argc, js::Value* vp);
191
192 extern bool
193 array_unshift(JSContext* cx, unsigned argc, js::Value* vp);
194
195 extern bool
196 array_slice(JSContext* cx, unsigned argc, js::Value* vp);
197
198 extern JSObject*
199 array_slice_dense(JSContext* cx, HandleObject obj, int32_t begin, int32_t end, HandleObject result);
200
201 /*
202 * Append the given (non-hole) value to the end of an array. The array must be
203 * a newborn array -- that is, one which has not been exposed to script for
204 * arbitrary manipulation. (This method optimizes on the assumption that
205 * extending the array to accommodate the element will never make the array
206 * sparse, which requires that the array be completely filled.)
207 */
208 extern bool
209 NewbornArrayPush(JSContext* cx, HandleObject obj, const Value& v);
210
211 extern JSObject*
212 ArrayConstructorOneArg(JSContext* cx, HandleObjectGroup group, int32_t lengthInt);
213
214 #ifdef DEBUG
215 extern bool
216 ArrayInfo(JSContext* cx, unsigned argc, Value* vp);
217 #endif
218
219 /* Array constructor native. Exposed only so the JIT can know its address. */
220 extern bool
221 ArrayConstructor(JSContext* cx, unsigned argc, Value* vp);
222
223 } /* namespace js */
224
225 #endif /* jsarray_h */
226