Array.h (7780B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 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 builtin_Array_h 10 #define builtin_Array_h 11 12 #include "mozilla/Attributes.h" 13 14 #include "vm/JSObject.h" 15 16 namespace js { 17 18 enum class ArraySortResult : uint32_t; 19 20 namespace jit { 21 class TrampolineNativeFrameLayout; 22 } 23 24 class ArrayObject; 25 class IteratorProperty; 26 27 MOZ_ALWAYS_INLINE bool IdIsIndex(jsid id, uint32_t* indexp) { 28 if (id.isInt()) { 29 int32_t i = id.toInt(); 30 MOZ_ASSERT(i >= 0); 31 *indexp = uint32_t(i); 32 return true; 33 } 34 35 if (MOZ_UNLIKELY(!id.isAtom())) { 36 return false; 37 } 38 39 JSAtom* atom = id.toAtom(); 40 return atom->isIndex(indexp); 41 } 42 43 // The methods below only create dense boxed arrays. 44 45 // Create a dense array with no capacity allocated, length set to 0, in the 46 // normal (i.e. non-tenured) heap. 47 extern ArrayObject* NewDenseEmptyArray(JSContext* cx); 48 49 // Create a dense array with no capacity allocated, length set to 0, in the 50 // tenured heap. 51 extern ArrayObject* NewTenuredDenseEmptyArray(JSContext* cx); 52 53 // Create a dense array with a set length, but without allocating space for the 54 // contents. This is useful, e.g., when accepting length from the user. 55 extern ArrayObject* NewDenseUnallocatedArray( 56 JSContext* cx, uint32_t length, NewObjectKind newKind = GenericObject); 57 58 // Create a dense array with length and capacity == 'length', initialized length 59 // set to 0. 60 extern ArrayObject* NewDenseFullyAllocatedArray( 61 JSContext* cx, uint32_t length, NewObjectKind newKind = GenericObject, 62 gc::AllocSite* site = nullptr); 63 64 // Create a dense array with length == 'length', initialized length set to 0, 65 // and capacity == 'length' clamped to EagerAllocationMaxLength. 66 extern ArrayObject* NewDensePartlyAllocatedArray( 67 JSContext* cx, uint32_t length, NewObjectKind newKind = GenericObject, 68 gc::AllocSite* site = nullptr); 69 70 // Like NewDensePartlyAllocatedArray, but the array will have |proto| as 71 // prototype (or Array.prototype if |proto| is nullptr). 72 extern ArrayObject* NewDensePartlyAllocatedArrayWithProto(JSContext* cx, 73 uint32_t length, 74 HandleObject proto); 75 76 // Create a dense array from the given array values, which must be rooted. 77 extern ArrayObject* NewDenseCopiedArray(JSContext* cx, uint32_t length, 78 const Value* values, 79 NewObjectKind newKind = GenericObject); 80 81 // Create a dense array from the given IteratorProperty values, which must be 82 // rooted. 83 extern ArrayObject* NewDenseCopiedArray(JSContext* cx, uint32_t length, 84 IteratorProperty* props, 85 NewObjectKind newKind = GenericObject); 86 87 // Like NewDenseCopiedArray, but the array will have |proto| as prototype (or 88 // Array.prototype if |proto| is nullptr). 89 extern ArrayObject* NewDenseCopiedArrayWithProto(JSContext* cx, uint32_t length, 90 const Value* values, 91 HandleObject proto); 92 93 // Create a dense array with the given shape and length. 94 extern ArrayObject* NewDenseFullyAllocatedArrayWithShape( 95 JSContext* cx, uint32_t length, Handle<SharedShape*> shape); 96 97 extern ArrayObject* NewArrayWithShape(JSContext* cx, uint32_t length, 98 Handle<Shape*> shape); 99 100 extern bool ToLength(JSContext* cx, HandleValue v, uint64_t* out); 101 102 extern bool GetLengthProperty(JSContext* cx, HandleObject obj, 103 uint64_t* lengthp); 104 105 extern bool SetLengthProperty(JSContext* cx, HandleObject obj, uint32_t length); 106 107 /* 108 * Copy 'length' elements from aobj to vp. 109 * 110 * This function assumes 'length' is effectively the result of calling 111 * GetLengthProperty on aobj. vp must point to rooted memory. 112 */ 113 extern bool GetElements(JSContext* cx, HandleObject aobj, uint32_t length, 114 js::Value* vp); 115 116 /* 117 * If the property at the given index exists, get its value into |vp| and set 118 * |*hole| to false. Otherwise set |*hole| to true and |vp| to Undefined. 119 */ 120 extern bool HasAndGetElement(JSContext* cx, HandleObject obj, uint64_t index, 121 bool* hole, MutableHandleValue vp); 122 123 /* Natives exposed for optimization by the interpreter and JITs. */ 124 125 extern bool array_includes(JSContext* cx, unsigned argc, js::Value* vp); 126 extern bool array_indexOf(JSContext* cx, unsigned argc, js::Value* vp); 127 extern bool array_lastIndexOf(JSContext* cx, unsigned argc, js::Value* vp); 128 extern bool array_pop(JSContext* cx, unsigned argc, js::Value* vp); 129 extern bool array_join(JSContext* cx, unsigned argc, js::Value* vp); 130 extern bool array_sort(JSContext* cx, unsigned argc, js::Value* vp); 131 132 extern void ArrayShiftMoveElements(ArrayObject* arr); 133 134 extern JSObject* ArraySliceDense(JSContext* cx, HandleObject obj, int32_t begin, 135 int32_t end, HandleObject result); 136 137 extern JSObject* ArgumentsSliceDense(JSContext* cx, HandleObject obj, 138 int32_t begin, int32_t end, 139 HandleObject result); 140 141 extern ArrayObject* NewArrayWithNullProto(JSContext* cx); 142 143 /* 144 * Append the given (non-hole) value to the end of an array. The array must be 145 * a newborn array -- that is, one which has not been exposed to script for 146 * arbitrary manipulation. (This method optimizes on the assumption that 147 * extending the array to accommodate the element will never make the array 148 * sparse, which requires that the array be completely filled.) 149 */ 150 extern bool NewbornArrayPush(JSContext* cx, HandleObject obj, const Value& v); 151 152 extern ArrayObject* ArrayConstructorOneArg(JSContext* cx, 153 Handle<ArrayObject*> templateObject, 154 int32_t lengthInt, 155 gc::AllocSite* site); 156 157 #ifdef DEBUG 158 extern bool ArrayInfo(JSContext* cx, unsigned argc, Value* vp); 159 #endif 160 161 /* Array constructor native. Exposed only so the JIT can know its address. */ 162 extern bool ArrayConstructor(JSContext* cx, unsigned argc, Value* vp); 163 164 // Like Array constructor, but doesn't perform GetPrototypeFromConstructor. 165 extern bool array_construct(JSContext* cx, unsigned argc, Value* vp); 166 167 extern JSString* ArrayToSource(JSContext* cx, HandleObject obj); 168 169 extern bool IsCrossRealmArrayConstructor(JSContext* cx, JSObject* obj, 170 bool* result); 171 172 extern bool ObjectMayHaveExtraIndexedOwnProperties(JSObject* obj); 173 174 extern bool ObjectMayHaveExtraIndexedProperties(JSObject* obj); 175 176 extern bool PrototypeMayHaveIndexedProperties(NativeObject* obj); 177 178 // JS::IsArray has multiple overloads, use js::IsArrayFromJit to disambiguate. 179 extern bool IsArrayFromJit(JSContext* cx, HandleObject obj, bool* isArray); 180 181 extern bool ArrayLengthGetter(JSContext* cx, HandleObject obj, HandleId id, 182 MutableHandleValue vp); 183 184 extern bool ArrayLengthSetter(JSContext* cx, HandleObject obj, HandleId id, 185 HandleValue v, ObjectOpResult& result); 186 187 extern ArraySortResult ArraySortFromJit( 188 JSContext* cx, jit::TrampolineNativeFrameLayout* frame); 189 190 bool IsArrayConstructor(const JSObject* obj); 191 192 bool intrinsic_CanOptimizeArraySpecies(JSContext* cx, unsigned argc, Value* vp); 193 194 } /* namespace js */ 195 196 #endif /* builtin_Array_h */