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