• 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 
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