Line data Source code
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 : MOZ_ALWAYS_INLINE bool
22 163980 : IdIsIndex(jsid id, uint32_t* indexp)
23 : {
24 163980 : if (JSID_IS_INT(id)) {
25 5360 : int32_t i = JSID_TO_INT(id);
26 5360 : MOZ_ASSERT(i >= 0);
27 5360 : *indexp = (uint32_t)i;
28 5360 : return true;
29 : }
30 :
31 158620 : if (MOZ_UNLIKELY(!JSID_IS_STRING(id)))
32 4560 : return false;
33 :
34 154060 : JSAtom* atom = JSID_TO_ATOM(id);
35 154060 : if (atom->length() == 0 || !JS7_ISDEC(atom->latin1OrTwoByteChar(0)))
36 154061 : return false;
37 :
38 0 : return js::StringIsArrayIndex(atom, indexp);
39 : }
40 :
41 : // The methods below only create dense boxed arrays.
42 :
43 : /* Create a dense array with no capacity allocated, length set to 0. */
44 : extern ArrayObject * JS_FASTCALL
45 : NewDenseEmptyArray(JSContext* cx, HandleObject proto = nullptr,
46 : NewObjectKind newKind = GenericObject);
47 :
48 : /*
49 : * Create a dense array with a set length, but without allocating space for the
50 : * contents. This is useful, e.g., when accepting length from the user.
51 : */
52 : extern ArrayObject * JS_FASTCALL
53 : NewDenseUnallocatedArray(JSContext* cx, uint32_t length, HandleObject proto = nullptr,
54 : NewObjectKind newKind = GenericObject);
55 :
56 : /*
57 : * Create a dense array with length and capacity == |length|, initialized length set to 0,
58 : * but with only |EagerAllocationMaxLength| elements allocated.
59 : */
60 : extern ArrayObject * JS_FASTCALL
61 : NewDensePartlyAllocatedArray(JSContext* cx, uint32_t length, HandleObject proto = nullptr,
62 : NewObjectKind newKind = GenericObject);
63 :
64 : /* Create a dense array with length and capacity == 'length', initialized length set to 0. */
65 : extern ArrayObject * JS_FASTCALL
66 : NewDenseFullyAllocatedArray(JSContext* cx, uint32_t length, HandleObject proto = nullptr,
67 : NewObjectKind newKind = GenericObject);
68 :
69 : /* Create a dense array from the given array values, which must be rooted */
70 : extern ArrayObject*
71 : NewDenseCopiedArray(JSContext* cx, uint32_t length, const Value* values,
72 : HandleObject proto = nullptr, NewObjectKind newKind = GenericObject);
73 :
74 : /* Create a dense array based on templateObject with the given length. */
75 : extern ArrayObject*
76 : NewDenseFullyAllocatedArrayWithTemplate(JSContext* cx, uint32_t length, JSObject* templateObject);
77 :
78 : /* Create a dense array with the same copy-on-write elements as another object. */
79 : extern JSObject*
80 : NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc::InitialHeap heap);
81 :
82 : // The methods below can create either boxed or unboxed arrays.
83 :
84 : extern JSObject*
85 : NewFullyAllocatedArrayTryUseGroup(JSContext* cx, HandleObjectGroup group, size_t length,
86 : NewObjectKind newKind = GenericObject);
87 :
88 : extern JSObject*
89 : NewPartlyAllocatedArrayTryUseGroup(JSContext* cx, HandleObjectGroup group, size_t length);
90 :
91 : extern JSObject*
92 : NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, HandleObject obj, size_t length,
93 : NewObjectKind newKind = GenericObject);
94 :
95 : extern JSObject*
96 : NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, HandleObject obj, size_t length);
97 :
98 : extern JSObject*
99 : NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
100 : NewObjectKind newKind = GenericObject);
101 :
102 : extern JSObject*
103 : NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, HandleObject proto);
104 :
105 : enum class ShouldUpdateTypes
106 : {
107 : Update,
108 : DontUpdate
109 : };
110 :
111 : extern bool
112 : MaybeAnalyzeBeforeCreatingLargeArray(JSContext* cx, HandleObjectGroup group,
113 : const Value* vp, size_t length);
114 :
115 : extern JSObject*
116 : NewCopiedArrayTryUseGroup(JSContext* cx, HandleObjectGroup group,
117 : const Value* vp, size_t length,
118 : NewObjectKind newKind = GenericObject,
119 : ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update);
120 :
121 : extern JSObject*
122 : NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_t length,
123 : HandleObject proto = nullptr);
124 :
125 : extern bool
126 : NewValuePair(JSContext* cx, const Value& val1, const Value& val2, MutableHandleValue rval);
127 :
128 : /*
129 : * Determines whether a write to the given element on |obj| should fail because
130 : * |obj| is an Array with a non-writable length, and writing that element would
131 : * increase the length of the array.
132 : */
133 : extern bool
134 : WouldDefinePastNonwritableLength(HandleNativeObject obj, uint32_t index);
135 :
136 : /*
137 : * Canonicalize |vp| to a uint32_t value potentially suitable for use as an
138 : * array length.
139 : */
140 : extern bool
141 : CanonicalizeArrayLengthValue(JSContext* cx, HandleValue v, uint32_t* canonicalized);
142 :
143 : extern bool
144 : GetLengthProperty(JSContext* cx, HandleObject obj, uint32_t* lengthp);
145 :
146 : extern bool
147 : SetLengthProperty(JSContext* cx, HandleObject obj, uint32_t length);
148 :
149 : extern bool
150 : ObjectMayHaveExtraIndexedProperties(JSObject* obj);
151 :
152 : /*
153 : * Copy 'length' elements from aobj to vp.
154 : *
155 : * This function assumes 'length' is effectively the result of calling
156 : * GetLengthProperty on aobj. vp must point to rooted memory.
157 : */
158 : extern bool
159 : GetElements(JSContext* cx, HandleObject aobj, uint32_t length, js::Value* vp);
160 :
161 : /* Natives exposed for optimization by the interpreter and JITs. */
162 :
163 : extern bool
164 : array_sort(JSContext* cx, unsigned argc, js::Value* vp);
165 :
166 : extern bool
167 : array_push(JSContext* cx, unsigned argc, js::Value* vp);
168 :
169 : extern bool
170 : array_pop(JSContext* cx, unsigned argc, js::Value* vp);
171 :
172 : extern bool
173 : array_join(JSContext* cx, unsigned argc, js::Value* vp);
174 :
175 : extern void
176 : ArrayShiftMoveElements(JSObject* obj);
177 :
178 : extern bool
179 : array_shift(JSContext* cx, unsigned argc, js::Value* vp);
180 :
181 : extern bool
182 : array_unshift(JSContext* cx, unsigned argc, js::Value* vp);
183 :
184 : extern bool
185 : array_slice(JSContext* cx, unsigned argc, js::Value* vp);
186 :
187 : extern JSObject*
188 : array_slice_dense(JSContext* cx, HandleObject obj, int32_t begin, int32_t end, HandleObject result);
189 :
190 : extern bool
191 : array_reverse(JSContext* cx, unsigned argc, js::Value* vp);
192 :
193 : extern bool
194 : array_splice(JSContext* cx, unsigned argc, js::Value* vp);
195 :
196 : extern const JSJitInfo array_splice_info;
197 :
198 : /*
199 : * Append the given (non-hole) value to the end of an array. The array must be
200 : * a newborn array -- that is, one which has not been exposed to script for
201 : * arbitrary manipulation. (This method optimizes on the assumption that
202 : * extending the array to accommodate the element will never make the array
203 : * sparse, which requires that the array be completely filled.)
204 : */
205 : extern bool
206 : NewbornArrayPush(JSContext* cx, HandleObject obj, const Value& v);
207 :
208 : extern JSObject*
209 : ArrayConstructorOneArg(JSContext* cx, HandleObjectGroup group, int32_t lengthInt);
210 :
211 : #ifdef DEBUG
212 : extern bool
213 : ArrayInfo(JSContext* cx, unsigned argc, Value* vp);
214 : #endif
215 :
216 : /* Array constructor native. Exposed only so the JIT can know its address. */
217 : extern bool
218 : ArrayConstructor(JSContext* cx, unsigned argc, Value* vp);
219 :
220 : // Like Array constructor, but doesn't perform GetPrototypeFromConstructor.
221 : extern bool
222 : array_construct(JSContext* cx, unsigned argc, Value* vp);
223 :
224 : extern bool
225 : IsWrappedArrayConstructor(JSContext* cx, const Value& v, bool* result);
226 :
227 : } /* namespace js */
228 :
229 : #endif /* jsarray_h */
|