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 12 // Has to be the last include (doesn't have include guards): 13 #include "src/objects/object-macros.h" 14 15 namespace v8 { 16 namespace internal { 17 18 #include "torque-generated/src/objects/js-array-tq.inc" 19 20 // The JSArray describes JavaScript Arrays 21 // Such an array can be in one of two modes: 22 // - fast, backing storage is a FixedArray and length <= elements.length(); 23 // Please note: push and pop can be used to grow and shrink the array. 24 // - slow, backing storage is a HashTable with numbers as keys. 25 class JSArray : public TorqueGeneratedJSArray<JSArray, JSObject> { 26 public: 27 // [length]: The length property. 28 DECL_ACCESSORS(length, Object) 29 DECL_RELAXED_GETTER(length, Object) 30 31 // Acquire/release semantics on this field are explicitly forbidden to avoid 32 // confusion, since the default setter uses relaxed semantics. If 33 // acquire/release semantics ever become necessary, the default setter should 34 // be reverted to non-atomic behavior, and setters with explicit tags 35 // introduced and used when required. 36 Object length(PtrComprCageBase cage_base, AcquireLoadTag tag) const = delete; 37 void set_length(Object value, ReleaseStoreTag tag, 38 WriteBarrierMode mode = UPDATE_WRITE_BARRIER) = delete; 39 40 // Overload the length setter to skip write barrier when the length 41 // is set to a smi. This matches the set function on FixedArray. 42 inline void set_length(Smi length); 43 44 static bool MayHaveReadOnlyLength(Map js_array_map); 45 static bool HasReadOnlyLength(Handle<JSArray> array); 46 static bool WouldChangeReadOnlyLength(Handle<JSArray> array, uint32_t index); 47 48 // Initialize the array with the given capacity. The function may 49 // fail due to out-of-memory situations, but only if the requested 50 // capacity is non-zero. 51 V8_EXPORT_PRIVATE static void Initialize(Handle<JSArray> array, int capacity, 52 int length = 0); 53 54 // If the JSArray has fast elements, and new_length would result in 55 // normalization, returns true. 56 bool SetLengthWouldNormalize(uint32_t new_length); 57 static inline bool SetLengthWouldNormalize(Heap* heap, uint32_t new_length); 58 59 // Initializes the array to a certain length. 60 V8_EXPORT_PRIVATE static Maybe<bool> SetLength(Handle<JSArray> array, 61 uint32_t length); 62 63 // Set the content of the array to the content of storage. 64 static inline void SetContent(Handle<JSArray> array, 65 Handle<FixedArrayBase> storage); 66 67 // ES6 9.4.2.1 68 V8_WARN_UNUSED_RESULT static Maybe<bool> DefineOwnProperty( 69 Isolate* isolate, Handle<JSArray> o, Handle<Object> name, 70 PropertyDescriptor* desc, Maybe<ShouldThrow> should_throw); 71 72 static bool AnythingToArrayLength(Isolate* isolate, 73 Handle<Object> length_object, 74 uint32_t* output); 75 V8_WARN_UNUSED_RESULT static Maybe<bool> ArraySetLength( 76 Isolate* isolate, Handle<JSArray> a, PropertyDescriptor* desc, 77 Maybe<ShouldThrow> should_throw); 78 79 // Support for Array.prototype.join(). 80 // Writes a fixed array of strings and separators to a single destination 81 // string. This helpers assumes the fixed array encodes separators in two 82 // ways: 83 // 1) Explicitly with a smi, whos value represents the number of repeated 84 // separators. 85 // 2) Implicitly between two consecutive strings a single separator. 86 // 87 // Here are some input/output examples given the separator string is ',': 88 // 89 // [1, 'hello', 2, 'world', 1] => ',hello,,world,' 90 // ['hello', 'world'] => 'hello,world' 91 // 92 // To avoid any allocations, this helper assumes the destination string is the 93 // exact length necessary to write the strings and separators from the fixed 94 // array. 95 // Since this is called via ExternalReferences, it uses raw Address values: 96 // - {raw_fixed_array} is a tagged FixedArray pointer. 97 // - {raw_separator} and {raw_dest} are tagged String pointers. 98 // - Returns a tagged String pointer. 99 static Address ArrayJoinConcatToSequentialString(Isolate* isolate, 100 Address raw_fixed_array, 101 intptr_t length, 102 Address raw_separator, 103 Address raw_dest); 104 105 // Checks whether the Array has the current realm's Array.prototype as its 106 // prototype. This function is best-effort and only gives a conservative 107 // approximation, erring on the side of false, in particular with respect 108 // to Proxies and objects with a hidden prototype. 109 inline bool HasArrayPrototype(Isolate* isolate); 110 111 // Dispatched behavior. 112 DECL_PRINTER(JSArray) 113 DECL_VERIFIER(JSArray) 114 115 // Number of element slots to pre-allocate for an empty array. 116 static const int kPreallocatedArrayElements = 4; 117 118 static const int kLengthDescriptorIndex = 0; 119 120 // Max. number of elements being copied in Array builtins. 121 static const int kMaxCopyElements = 100; 122 123 // Valid array indices range from +0 <= i < 2^32 - 1 (kMaxUInt32). 124 static constexpr uint32_t kMaxArrayLength = JSObject::kMaxElementCount; 125 static constexpr uint32_t kMaxArrayIndex = JSObject::kMaxElementIndex; 126 STATIC_ASSERT(kMaxArrayLength == kMaxUInt32); 127 STATIC_ASSERT(kMaxArrayIndex == kMaxUInt32 - 1); 128 129 // This constant is somewhat arbitrary. Any large enough value would work. 130 static constexpr uint32_t kMaxFastArrayLength = 32 * 1024 * 1024; 131 STATIC_ASSERT(kMaxFastArrayLength <= kMaxArrayLength); 132 133 // Min. stack size for detecting an Array.prototype.join() call cycle. 134 static const uint32_t kMinJoinStackSize = 2; 135 136 static const int kInitialMaxFastElementArray = 137 (kMaxRegularHeapObjectSize - FixedArray::kHeaderSize - kHeaderSize - 138 AllocationMemento::kSize) >> 139 kDoubleSizeLog2; 140 141 TQ_OBJECT_CONSTRUCTORS(JSArray) 142 }; 143 144 // The JSArrayIterator describes JavaScript Array Iterators Objects, as 145 // defined in ES section #sec-array-iterator-objects. 146 class JSArrayIterator 147 : public TorqueGeneratedJSArrayIterator<JSArrayIterator, JSObject> { 148 public: 149 DECL_PRINTER(JSArrayIterator) 150 DECL_VERIFIER(JSArrayIterator) 151 152 // [kind]: the [[ArrayIterationKind]] inobject property. 153 inline IterationKind kind() const; 154 inline void set_kind(IterationKind kind); 155 156 private: 157 DECL_INT_ACCESSORS(raw_kind) 158 159 TQ_OBJECT_CONSTRUCTORS(JSArrayIterator) 160 }; 161 162 } // namespace internal 163 } // namespace v8 164 165 #include "src/objects/object-macros-undef.h" 166 167 #endif // V8_OBJECTS_JS_ARRAY_H_ 168