js-array.h 7.39 KB
Newer Older
1 2 3 4 5 6 7
// 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_

8
#include "src/objects/allocation-site.h"
9
#include "src/objects/fixed-array.h"
10
#include "src/objects/js-objects.h"
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

// 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
55
  V8_WARN_UNUSED_RESULT static Maybe<bool> DefineOwnProperty(
56 57 58 59 60 61
      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);
62 63 64
  V8_WARN_UNUSED_RESULT static Maybe<bool> ArraySetLength(
      Isolate* isolate, Handle<JSArray> a, PropertyDescriptor* desc,
      ShouldThrow should_throw);
65

66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
  // 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.
  static String* ArrayJoinConcatToSequentialString(Isolate* isolate,
                                                   FixedArray* fixed_array,
                                                   intptr_t length,
                                                   String* separator,
                                                   String* dest);

88 89 90 91 92 93 94 95 96
  // 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.
97
  DECL_PRINTER(JSArray)
98 99 100 101 102 103 104 105 106
  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;

107 108
  static const int kLengthDescriptorIndex = 0;

109 110 111 112 113 114
  // 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;

115 116 117
  // Min. stack size for detecting an Array.prototype.join() call cycle.
  static const uint32_t kMinJoinStackSize = 2;

118 119 120 121 122
  static const int kInitialMaxFastElementArray =
      (kMaxRegularHeapObjectSize - FixedArray::kHeaderSize - kSize -
       AllocationMemento::kSize) >>
      kDoubleSizeLog2;

123 124 125
  // Valid array indices range from +0 <= i < 2^32 - 1 (kMaxUInt32).
  static const uint32_t kMaxArrayIndex = kMaxUInt32 - 1;

126 127 128 129 130 131 132
 private:
  DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray);
};

Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context,
                                       Handle<Map> initial_map);

133 134
// The JSArrayIterator describes JavaScript Array Iterators Objects, as
// defined in ES section #sec-array-iterator-objects.
135 136
class JSArrayIterator : public JSObject {
 public:
137
  DECL_PRINTER(JSArrayIterator)
138 139 140 141
  DECL_VERIFIER(JSArrayIterator)

  DECL_CAST(JSArrayIterator)

142 143
  // [iterated_object]: the [[IteratedObject]] inobject property.
  DECL_ACCESSORS(iterated_object, Object)
144

145
  // [next_index]: The [[ArrayIteratorNextIndex]] inobject property.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
  // 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().
168
  DECL_ACCESSORS(next_index, Object)
169

170 171 172
  // [kind]: the [[ArrayIterationKind]] inobject property.
  inline IterationKind kind() const;
  inline void set_kind(IterationKind kind);
173 174 175

  static const int kIteratedObjectOffset = JSObject::kHeaderSize;
  static const int kNextIndexOffset = kIteratedObjectOffset + kPointerSize;
176 177
  static const int kKindOffset = kNextIndexOffset + kPointerSize;
  static const int kSize = kKindOffset + kPointerSize;
178 179 180 181 182 183 184 185 186 187 188

 private:
  DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayIterator);
};

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_JS_ARRAY_H_