blob: 05354eaccf1359509ac6189fd5208b94620a0f09 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004
5#ifndef V8_ELEMENTS_H_
6#define V8_ELEMENTS_H_
7
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/elements-kind.h"
9#include "src/heap/heap.h"
10#include "src/isolate.h"
11#include "src/objects.h"
Ben Murdoch69a99ed2011-11-30 16:03:39 +000012
13namespace v8 {
14namespace internal {
15
16// Abstract base class for handles that can operate on objects with differing
17// ElementsKinds.
18class ElementsAccessor {
19 public:
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020 explicit ElementsAccessor(const char* name) : name_(name) { }
Ben Murdoch69a99ed2011-11-30 16:03:39 +000021 virtual ~ElementsAccessor() { }
Ben Murdoch69a99ed2011-11-30 16:03:39 +000022
Ben Murdoch3ef787d2012-04-12 10:51:47 +010023 virtual ElementsKind kind() const = 0;
24 const char* name() const { return name_; }
25
Ben Murdochb8a8cc12014-11-26 15:28:44 +000026 // Checks the elements of an object for consistency, asserting when a problem
27 // is found.
28 virtual void Validate(Handle<JSObject> obj) = 0;
29
Ben Murdoch3ef787d2012-04-12 10:51:47 +010030 // Returns true if a holder contains an element with the specified key
31 // without iterating up the prototype chain. The caller can optionally pass
32 // in the backing store to use for the check, which must be compatible with
33 // the ElementsKind of the ElementsAccessor. If backing_store is NULL, the
34 // holder->elements() is used as the backing store.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035 virtual bool HasElement(
36 Handle<Object> receiver,
37 Handle<JSObject> holder,
38 uint32_t key,
39 Handle<FixedArrayBase> backing_store) = 0;
40
41 inline bool HasElement(
42 Handle<Object> receiver,
43 Handle<JSObject> holder,
44 uint32_t key) {
45 return HasElement(receiver, holder, key, handle(holder->elements()));
46 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010047
48 // Returns the element with the specified key or undefined if there is no such
49 // element. This method doesn't iterate up the prototype chain. The caller
50 // can optionally pass in the backing store to use for the check, which must
51 // be compatible with the ElementsKind of the ElementsAccessor. If
52 // backing_store is NULL, the holder->elements() is used as the backing store.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000053 MUST_USE_RESULT virtual MaybeHandle<Object> Get(
54 Handle<Object> receiver,
55 Handle<JSObject> holder,
56 uint32_t key,
57 Handle<FixedArrayBase> backing_store) = 0;
58
59 MUST_USE_RESULT inline MaybeHandle<Object> Get(
60 Handle<Object> receiver,
61 Handle<JSObject> holder,
62 uint32_t key) {
63 return Get(receiver, holder, key, handle(holder->elements()));
64 }
65
66 // Returns an element's attributes, or ABSENT if there is no such
67 // element. This method doesn't iterate up the prototype chain. The caller
68 // can optionally pass in the backing store to use for the check, which must
69 // be compatible with the ElementsKind of the ElementsAccessor. If
70 // backing_store is NULL, the holder->elements() is used as the backing store.
71 MUST_USE_RESULT virtual PropertyAttributes GetAttributes(
72 Handle<Object> receiver,
73 Handle<JSObject> holder,
74 uint32_t key,
75 Handle<FixedArrayBase> backing_store) = 0;
76
77 MUST_USE_RESULT inline PropertyAttributes GetAttributes(
78 Handle<Object> receiver,
79 Handle<JSObject> holder,
80 uint32_t key) {
81 return GetAttributes(receiver, holder, key, handle(holder->elements()));
82 }
83
84 // Returns an element's accessors, or NULL if the element does not exist or
85 // is plain. This method doesn't iterate up the prototype chain. The caller
86 // can optionally pass in the backing store to use for the check, which must
87 // be compatible with the ElementsKind of the ElementsAccessor. If
88 // backing_store is NULL, the holder->elements() is used as the backing store.
89 MUST_USE_RESULT virtual MaybeHandle<AccessorPair> GetAccessorPair(
90 Handle<Object> receiver,
91 Handle<JSObject> holder,
92 uint32_t key,
93 Handle<FixedArrayBase> backing_store) = 0;
94
95 MUST_USE_RESULT inline MaybeHandle<AccessorPair> GetAccessorPair(
96 Handle<Object> receiver,
97 Handle<JSObject> holder,
98 uint32_t key) {
99 return GetAccessorPair(receiver, holder, key, handle(holder->elements()));
100 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100101
102 // Modifies the length data property as specified for JSArrays and resizes the
103 // underlying backing store accordingly. The method honors the semantics of
104 // changing array sizes as defined in EcmaScript 5.1 15.4.5.2, i.e. array that
105 // have non-deletable elements can only be shrunk to the size of highest
106 // element that is non-deletable.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107 MUST_USE_RESULT virtual MaybeHandle<Object> SetLength(
108 Handle<JSArray> holder,
109 Handle<Object> new_length) = 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100110
111 // Modifies both the length and capacity of a JSArray, resizing the underlying
112 // backing store as necessary. This method does NOT honor the semantics of
113 // EcmaScript 5.1 15.4.5.2, arrays can be shrunk beyond non-deletable
114 // elements. This method should only be called for array expansion OR by
115 // runtime JavaScript code that use InternalArrays and don't care about
116 // EcmaScript 5.1 semantics.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117 virtual void SetCapacityAndLength(
118 Handle<JSArray> array,
119 int capacity,
120 int length) = 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100121
122 // Deletes an element in an object, returning a new elements backing store.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000123 MUST_USE_RESULT virtual MaybeHandle<Object> Delete(
124 Handle<JSObject> holder,
125 uint32_t key,
126 JSReceiver::DeleteMode mode) = 0;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000127
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100128 // If kCopyToEnd is specified as the copy_size to CopyElements, it copies all
129 // of elements from source after source_start to the destination array.
130 static const int kCopyToEnd = -1;
131 // If kCopyToEndAndInitializeToHole is specified as the copy_size to
132 // CopyElements, it copies all of elements from source after source_start to
133 // destination array, padding any remaining uninitialized elements in the
134 // destination array with the hole.
135 static const int kCopyToEndAndInitializeToHole = -2;
136
137 // Copy elements from one backing store to another. Typically, callers specify
138 // the source JSObject or JSArray in source_holder. If the holder's backing
139 // store is available, it can be passed in source and source_holder is
140 // ignored.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000141 virtual void CopyElements(
142 Handle<FixedArrayBase> source,
143 uint32_t source_start,
144 ElementsKind source_kind,
145 Handle<FixedArrayBase> destination,
146 uint32_t destination_start,
147 int copy_size) = 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100148
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400149 // NOTE: this method violates the handlified function signature convention:
150 // raw pointer parameter |source_holder| in the function that allocates.
151 // This is done intentionally to avoid ArrayConcat() builtin performance
152 // degradation.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000153 virtual void CopyElements(
154 JSObject* source_holder,
155 uint32_t source_start,
156 ElementsKind source_kind,
157 Handle<FixedArrayBase> destination,
158 uint32_t destination_start,
159 int copy_size) = 0;
160
161 inline void CopyElements(
162 Handle<JSObject> from_holder,
163 Handle<FixedArrayBase> to,
164 ElementsKind from_kind) {
165 CopyElements(
166 *from_holder, 0, from_kind, to, 0, kCopyToEndAndInitializeToHole);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100167 }
168
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 MUST_USE_RESULT virtual MaybeHandle<FixedArray> AddElementsToFixedArray(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400170 Handle<Object> receiver, Handle<JSObject> holder, Handle<FixedArray> to,
171 Handle<FixedArrayBase> from, FixedArray::KeyFilter filter) = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000172
173 MUST_USE_RESULT inline MaybeHandle<FixedArray> AddElementsToFixedArray(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400174 Handle<Object> receiver, Handle<JSObject> holder, Handle<FixedArray> to,
175 FixedArray::KeyFilter filter) {
176 return AddElementsToFixedArray(receiver, holder, to,
177 handle(holder->elements()), filter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000178 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000179
180 // Returns a shared ElementsAccessor for the specified ElementsKind.
Ben Murdoch589d6972011-11-30 16:04:58 +0000181 static ElementsAccessor* ForKind(ElementsKind elements_kind) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400182 DCHECK(static_cast<int>(elements_kind) < kElementsKindCount);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000183 return elements_accessors_[elements_kind];
184 }
185
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000186 static ElementsAccessor* ForArray(Handle<FixedArrayBase> array);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000187
188 static void InitializeOncePerProcess();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 static void TearDown();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000190
191 protected:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 friend class SloppyArgumentsElementsAccessor;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000193
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 virtual uint32_t GetCapacity(Handle<FixedArrayBase> backing_store) = 0;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000195
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100196 // Element handlers distinguish between indexes and keys when they manipulate
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000197 // elements. Indexes refer to elements in terms of their location in the
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100198 // underlying storage's backing store representation, and are between 0 and
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000199 // GetCapacity. Keys refer to elements in terms of the value that would be
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100200 // specified in JavaScript to access the element. In most implementations,
201 // keys are equivalent to indexes, and GetKeyForIndex returns the same value
202 // it is passed. In the NumberDictionary ElementsAccessor, GetKeyForIndex maps
203 // the index to a key using the KeyAt method on the NumberDictionary.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204 virtual uint32_t GetKeyForIndex(Handle<FixedArrayBase> backing_store,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000205 uint32_t index) = 0;
206
207 private:
208 static ElementsAccessor** elements_accessors_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100209 const char* name_;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000210
211 DISALLOW_COPY_AND_ASSIGN(ElementsAccessor);
212};
213
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214void CheckArrayAbuse(Handle<JSObject> obj, const char* op, uint32_t key,
215 bool allow_appending = false);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100216
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217MUST_USE_RESULT MaybeHandle<Object> ArrayConstructInitializeElements(
218 Handle<JSArray> array,
219 Arguments* args);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100220
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000221} } // namespace v8::internal
222
223#endif // V8_ELEMENTS_H_