• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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