// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_OBJECTS_JS_ARRAY_H_ #define V8_OBJECTS_JS_ARRAY_H_ #include "src/objects.h" #include "src/objects/fixed-array.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" namespace v8 { namespace internal { // The JSArray describes JavaScript Arrays // Such an array can be in one of two modes: // - fast, backing storage is a FixedArray and length <= elements.length(); // Please note: push and pop can be used to grow and shrink the array. // - slow, backing storage is a HashTable with numbers as keys. class JSArray : public JSObject { public: // [length]: The length property. DECL_ACCESSORS(length, Object) // Overload the length setter to skip write barrier when the length // is set to a smi. This matches the set function on FixedArray. inline void set_length(Smi* length); static bool HasReadOnlyLength(Handle<JSArray> array); static bool WouldChangeReadOnlyLength(Handle<JSArray> array, uint32_t index); // Initialize the array with the given capacity. The function may // fail due to out-of-memory situations, but only if the requested // capacity is non-zero. static void Initialize(Handle<JSArray> array, int capacity, int length = 0); // If the JSArray has fast elements, and new_length would result in // normalization, returns true. bool SetLengthWouldNormalize(uint32_t new_length); static inline bool SetLengthWouldNormalize(Heap* heap, uint32_t new_length); // Initializes the array to a certain length. inline bool AllowsSetLength(); static void SetLength(Handle<JSArray> array, uint32_t length); // Set the content of the array to the content of storage. static inline void SetContent(Handle<JSArray> array, Handle<FixedArrayBase> storage); // ES6 9.4.2.1 V8_WARN_UNUSED_RESULT static Maybe<bool> DefineOwnProperty( Isolate* isolate, Handle<JSArray> o, Handle<Object> name, PropertyDescriptor* desc, ShouldThrow should_throw); static bool AnythingToArrayLength(Isolate* isolate, Handle<Object> length_object, uint32_t* output); V8_WARN_UNUSED_RESULT static Maybe<bool> ArraySetLength( Isolate* isolate, Handle<JSArray> a, PropertyDescriptor* desc, ShouldThrow should_throw); // Checks whether the Array has the current realm's Array.prototype as its // prototype. This function is best-effort and only gives a conservative // approximation, erring on the side of false, in particular with respect // to Proxies and objects with a hidden prototype. inline bool HasArrayPrototype(Isolate* isolate); DECL_CAST(JSArray) // Dispatched behavior. DECL_PRINTER(JSArray) DECL_VERIFIER(JSArray) // Number of element slots to pre-allocate for an empty array. static const int kPreallocatedArrayElements = 4; // Layout description. static const int kLengthOffset = JSObject::kHeaderSize; static const int kSize = kLengthOffset + kPointerSize; static const int kLengthDescriptorIndex = 0; // Max. number of elements being copied in Array builtins. static const int kMaxCopyElements = 100; // This constant is somewhat arbitrary. Any large enough value would work. static const uint32_t kMaxFastArrayLength = 32 * 1024 * 1024; static const int kInitialMaxFastElementArray = (kMaxRegularHeapObjectSize - FixedArray::kHeaderSize - kSize - AllocationMemento::kSize) >> kDoubleSizeLog2; // Valid array indices range from +0 <= i < 2^32 - 1 (kMaxUInt32). static const uint32_t kMaxArrayIndex = kMaxUInt32 - 1; private: DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray); }; Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context, Handle<Map> initial_map); // The JSArrayIterator describes JavaScript Array Iterators Objects, as // defined in ES section #sec-array-iterator-objects. class JSArrayIterator : public JSObject { public: DECL_PRINTER(JSArrayIterator) DECL_VERIFIER(JSArrayIterator) DECL_CAST(JSArrayIterator) // [iterated_object]: the [[IteratedObject]] inobject property. DECL_ACCESSORS(iterated_object, Object) // [next_index]: The [[ArrayIteratorNextIndex]] inobject property. // The next_index is always a positive integer, and it points to // the next index that is to be returned by this iterator. It's // possible range is fixed depending on the [[iterated_object]]: // // 1. For JSArray's the next_index is always in Unsigned32 // range, and when the iterator reaches the end it's set // to kMaxUInt32 to indicate that this iterator should // never produce values anymore even if the "length" // property of the JSArray changes at some later point. // 2. For JSTypedArray's the next_index is always in // UnsignedSmall range, and when the iterator terminates // it's set to Smi::kMaxValue. // 3. For all other JSReceiver's it's always between 0 and // kMaxSafeInteger, and the latter value is used to mark // termination. // // It's important that for 1. and 2. the value fits into the // Unsigned32 range (UnsignedSmall is a subset of Unsigned32), // since we use this knowledge in the fast-path for the array // iterator next calls in TurboFan (in the JSCallReducer) to // keep the index in Word32 representation. This invariant is // checked in JSArrayIterator::JSArrayIteratorVerify(). DECL_ACCESSORS(next_index, Object) // [kind]: the [[ArrayIterationKind]] inobject property. inline IterationKind kind() const; inline void set_kind(IterationKind kind); static const int kIteratedObjectOffset = JSObject::kHeaderSize; static const int kNextIndexOffset = kIteratedObjectOffset + kPointerSize; static const int kKindOffset = kNextIndexOffset + kPointerSize; static const int kSize = kKindOffset + kPointerSize; private: DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayIterator); }; } // namespace internal } // namespace v8 #include "src/objects/object-macros-undef.h" #endif // V8_OBJECTS_JS_ARRAY_H_