blob: 843fde71b0bb6238dd9bade7f41fdde599857fb5 [file] [log] [blame]
// 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/allocation-site.h"
#include "src/objects/fixed-array.h"
#include "src/objects/js-objects.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);
// Support for Array.prototype.join().
// Writes a fixed array of strings and separators to a single destination
// string. This helpers assumes the fixed array encodes separators in two
// ways:
// 1) Explicitly with a smi, whos value represents the number of repeated
// separators.
// 2) Implicitly between two consecutive strings a single separator.
//
// Here are some input/output examples given the separator string is ',':
//
// [1, 'hello', 2, 'world', 1] => ',hello,,world,'
// ['hello', 'world'] => 'hello,world'
//
// To avoid any allocations, this helper assumes the destination string is the
// exact length necessary to write the strings and separators from the fixed
// array.
// Since this is called via ExternalReferences, it uses raw Address values:
// - {raw_fixed_array} is a tagged FixedArray pointer.
// - {raw_separator} and {raw_dest} are tagged String pointers.
// - Returns a tagged String pointer.
static Address ArrayJoinConcatToSequentialString(Isolate* isolate,
Address raw_fixed_array,
intptr_t length,
Address raw_separator,
Address raw_dest);
// 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_CAST2(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.
#define JS_ARRAY_FIELDS(V) \
V(kLengthOffset, kTaggedSize) \
/* Header size. */ \
V(kSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, JS_ARRAY_FIELDS)
#undef JS_ARRAY_FIELDS
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;
// Min. stack size for detecting an Array.prototype.join() call cycle.
static const uint32_t kMinJoinStackSize = 2;
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;
OBJECT_CONSTRUCTORS(JSArray, JSObject);
};
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_CAST2(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);
// Layout description.
#define JS_ARRAY_ITERATOR_FIELDS(V) \
V(kIteratedObjectOffset, kTaggedSize) \
V(kNextIndexOffset, kTaggedSize) \
V(kKindOffset, kTaggedSize) \
/* Header size. */ \
V(kSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, JS_ARRAY_ITERATOR_FIELDS)
#undef JS_ARRAY_ITERATOR_FIELDS
OBJECT_CONSTRUCTORS(JSArrayIterator, JSObject);
};
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_JS_ARRAY_H_