My favorites | Sign in
v8
Project Home Downloads Wiki Issues Source Code Search
Checkout   Browse   Changes  
Changes to /trunk/src/elements.cc
r12566 vs. r12661 Compare: vs.  Format:
Revision r12661
Go to: 
Project members, sign in to write a code review
/trunk/src/elements.cc   r12566 /trunk/src/elements.cc   r12661
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "objects.h" 30 #include "objects.h"
31 #include "elements.h" 31 #include "elements.h"
32 #include "utils.h" 32 #include "utils.h"
33 33
34 34
35 // Each concrete ElementsAccessor can handle exactly one ElementsKind, 35 // Each concrete ElementsAccessor can handle exactly one ElementsKind,
36 // several abstract ElementsAccessor classes are used to allow sharing 36 // several abstract ElementsAccessor classes are used to allow sharing
37 // common code. 37 // common code.
38 // 38 //
39 // Inheritance hierarchy: 39 // Inheritance hierarchy:
40 // - ElementsAccessorBase (abstract) 40 // - ElementsAccessorBase (abstract)
41 // - FastElementsAccessor (abstract) 41 // - FastElementsAccessor (abstract)
42 // - FastSmiOrObjectElementsAccessor 42 // - FastSmiOrObjectElementsAccessor
43 // - FastPackedSmiElementsAccessor 43 // - FastPackedSmiElementsAccessor
44 // - FastHoleySmiElementsAccessor 44 // - FastHoleySmiElementsAccessor
45 // - FastPackedObjectElementsAccessor 45 // - FastPackedObjectElementsAccessor
46 // - FastHoleyObjectElementsAccessor 46 // - FastHoleyObjectElementsAccessor
47 // - FastDoubleElementsAccessor 47 // - FastDoubleElementsAccessor
48 // - FastPackedDoubleElementsAccessor 48 // - FastPackedDoubleElementsAccessor
49 // - FastHoleyDoubleElementsAccessor 49 // - FastHoleyDoubleElementsAccessor
50 // - ExternalElementsAccessor (abstract) 50 // - ExternalElementsAccessor (abstract)
51 // - ExternalByteElementsAccessor 51 // - ExternalByteElementsAccessor
52 // - ExternalUnsignedByteElementsAccessor 52 // - ExternalUnsignedByteElementsAccessor
53 // - ExternalShortElementsAccessor 53 // - ExternalShortElementsAccessor
54 // - ExternalUnsignedShortElementsAccessor 54 // - ExternalUnsignedShortElementsAccessor
55 // - ExternalIntElementsAccessor 55 // - ExternalIntElementsAccessor
56 // - ExternalUnsignedIntElementsAccessor 56 // - ExternalUnsignedIntElementsAccessor
57 // - ExternalFloatElementsAccessor 57 // - ExternalFloatElementsAccessor
58 // - ExternalDoubleElementsAccessor 58 // - ExternalDoubleElementsAccessor
59 // - PixelElementsAccessor 59 // - PixelElementsAccessor
60 // - DictionaryElementsAccessor 60 // - DictionaryElementsAccessor
61 // - NonStrictArgumentsElementsAccessor 61 // - NonStrictArgumentsElementsAccessor
62 62
63 63
64 namespace v8 { 64 namespace v8 {
65 namespace internal { 65 namespace internal {
66 66
67 67
68 static const int kPackedSizeNotKnown = -1; 68 static const int kPackedSizeNotKnown = -1;
69 69
70 70
71 // First argument in list is the accessor class, the second argument is the 71 // First argument in list is the accessor class, the second argument is the
72 // accessor ElementsKind, and the third is the backing store class. Use the 72 // accessor ElementsKind, and the third is the backing store class. Use the
73 // fast element handler for smi-only arrays. The implementation is currently 73 // fast element handler for smi-only arrays. The implementation is currently
74 // identical. Note that the order must match that of the ElementsKind enum for 74 // identical. Note that the order must match that of the ElementsKind enum for
75 // the |accessor_array[]| below to work. 75 // the |accessor_array[]| below to work.
76 #define ELEMENTS_LIST(V) \ 76 #define ELEMENTS_LIST(V) \
77 V(FastPackedSmiElementsAccessor, FAST_SMI_ELEMENTS, FixedArray) \ 77 V(FastPackedSmiElementsAccessor, FAST_SMI_ELEMENTS, FixedArray) \
78 V(FastHoleySmiElementsAccessor, FAST_HOLEY_SMI_ELEMENTS, \ 78 V(FastHoleySmiElementsAccessor, FAST_HOLEY_SMI_ELEMENTS, \
79 FixedArray) \ 79 FixedArray) \
80 V(FastPackedObjectElementsAccessor, FAST_ELEMENTS, FixedArray) \ 80 V(FastPackedObjectElementsAccessor, FAST_ELEMENTS, FixedArray) \
81 V(FastHoleyObjectElementsAccessor, FAST_HOLEY_ELEMENTS, FixedArray) \ 81 V(FastHoleyObjectElementsAccessor, FAST_HOLEY_ELEMENTS, FixedArray) \
82 V(FastPackedDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, \ 82 V(FastPackedDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, \
83 FixedDoubleArray) \ 83 FixedDoubleArray) \
84 V(FastHoleyDoubleElementsAccessor, FAST_HOLEY_DOUBLE_ELEMENTS, \ 84 V(FastHoleyDoubleElementsAccessor, FAST_HOLEY_DOUBLE_ELEMENTS, \
85 FixedDoubleArray) \ 85 FixedDoubleArray) \
86 V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, \ 86 V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, \
87 SeededNumberDictionary) \ 87 SeededNumberDictionary) \
88 V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS, \ 88 V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS, \
89 FixedArray) \ 89 FixedArray) \
90 V(ExternalByteElementsAccessor, EXTERNAL_BYTE_ELEMENTS, \ 90 V(ExternalByteElementsAccessor, EXTERNAL_BYTE_ELEMENTS, \
91 ExternalByteArray) \ 91 ExternalByteArray) \
92 V(ExternalUnsignedByteElementsAccessor, \ 92 V(ExternalUnsignedByteElementsAccessor, \
93 EXTERNAL_UNSIGNED_BYTE_ELEMENTS, ExternalUnsignedByteArray) \ 93 EXTERNAL_UNSIGNED_BYTE_ELEMENTS, ExternalUnsignedByteArray) \
94 V(ExternalShortElementsAccessor, EXTERNAL_SHORT_ELEMENTS, \ 94 V(ExternalShortElementsAccessor, EXTERNAL_SHORT_ELEMENTS, \
95 ExternalShortArray) \ 95 ExternalShortArray) \
96 V(ExternalUnsignedShortElementsAccessor, \ 96 V(ExternalUnsignedShortElementsAccessor, \
97 EXTERNAL_UNSIGNED_SHORT_ELEMENTS, ExternalUnsignedShortArray) \ 97 EXTERNAL_UNSIGNED_SHORT_ELEMENTS, ExternalUnsignedShortArray) \
98 V(ExternalIntElementsAccessor, EXTERNAL_INT_ELEMENTS, \ 98 V(ExternalIntElementsAccessor, EXTERNAL_INT_ELEMENTS, \
99 ExternalIntArray) \ 99 ExternalIntArray) \
100 V(ExternalUnsignedIntElementsAccessor, \ 100 V(ExternalUnsignedIntElementsAccessor, \
101 EXTERNAL_UNSIGNED_INT_ELEMENTS, ExternalUnsignedIntArray) \ 101 EXTERNAL_UNSIGNED_INT_ELEMENTS, ExternalUnsignedIntArray) \
102 V(ExternalFloatElementsAccessor, \ 102 V(ExternalFloatElementsAccessor, \
103 EXTERNAL_FLOAT_ELEMENTS, ExternalFloatArray) \ 103 EXTERNAL_FLOAT_ELEMENTS, ExternalFloatArray) \
104 V(ExternalDoubleElementsAccessor, \ 104 V(ExternalDoubleElementsAccessor, \
105 EXTERNAL_DOUBLE_ELEMENTS, ExternalDoubleArray) \ 105 EXTERNAL_DOUBLE_ELEMENTS, ExternalDoubleArray) \
106 V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS, ExternalPixelArray) 106 V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS, ExternalPixelArray)
107 107
108 108
109 template<ElementsKind Kind> class ElementsKindTraits { 109 template<ElementsKind Kind> class ElementsKindTraits {
110 public: 110 public:
111 typedef FixedArrayBase BackingStore; 111 typedef FixedArrayBase BackingStore;
112 }; 112 };
113 113
114 #define ELEMENTS_TRAITS(Class, KindParam, Store) \ 114 #define ELEMENTS_TRAITS(Class, KindParam, Store) \
115 template<> class ElementsKindTraits<KindParam> { \ 115 template<> class ElementsKindTraits<KindParam> { \
116 public: \ 116 public: \
117 static const ElementsKind Kind = KindParam; \ 117 static const ElementsKind Kind = KindParam; \
118 typedef Store BackingStore; \ 118 typedef Store BackingStore; \
119 }; 119 };
120 ELEMENTS_LIST(ELEMENTS_TRAITS) 120 ELEMENTS_LIST(ELEMENTS_TRAITS)
121 #undef ELEMENTS_TRAITS 121 #undef ELEMENTS_TRAITS
122 122
123 123
124 ElementsAccessor** ElementsAccessor::elements_accessors_; 124 ElementsAccessor** ElementsAccessor::elements_accessors_;
125 125
126 126
127 static bool HasKey(FixedArray* array, Object* key) { 127 static bool HasKey(FixedArray* array, Object* key) {
128 int len0 = array->length(); 128 int len0 = array->length();
129 for (int i = 0; i < len0; i++) { 129 for (int i = 0; i < len0; i++) {
130 Object* element = array->get(i); 130 Object* element = array->get(i);
131 if (element->IsSmi() && element == key) return true; 131 if (element->IsSmi() && element == key) return true;
132 if (element->IsString() && 132 if (element->IsString() &&
133 key->IsString() && String::cast(element)->Equals(String::cast(key))) { 133 key->IsString() && String::cast(element)->Equals(String::cast(key))) {
134 return true; 134 return true;
135 } 135 }
136 } 136 }
137 return false; 137 return false;
138 } 138 }
139 139
140 140
141 static Failure* ThrowArrayLengthRangeError(Heap* heap) { 141 static Failure* ThrowArrayLengthRangeError(Heap* heap) {
142 HandleScope scope(heap->isolate()); 142 HandleScope scope(heap->isolate());
143 return heap->isolate()->Throw( 143 return heap->isolate()->Throw(
144 *heap->isolate()->factory()->NewRangeError("invalid_array_length", 144 *heap->isolate()->factory()->NewRangeError("invalid_array_length",
145 HandleVector<Object>(NULL, 0))); 145 HandleVector<Object>(NULL, 0)));
146 } 146 }
147 147
148 148
149 void CopyObjectToObjectElements(FixedArray* from, 149 void CopyObjectToObjectElements(FixedArray* from,
150 ElementsKind from_kind, 150 ElementsKind from_kind,
151 uint32_t from_start, 151 uint32_t from_start,
152 FixedArray* to, 152 FixedArray* to,
153 ElementsKind to_kind, 153 ElementsKind to_kind,
154 uint32_t to_start, 154 uint32_t to_start,
155 int raw_copy_size) { 155 int raw_copy_size) {
156 ASSERT(to->map() != HEAP->fixed_cow_array_map()); 156 ASSERT(to->map() != HEAP->fixed_cow_array_map());
157 int copy_size = raw_copy_size; 157 int copy_size = raw_copy_size;
158 if (raw_copy_size < 0) { 158 if (raw_copy_size < 0) {
159 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || 159 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
160 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); 160 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
161 copy_size = Min(from->length() - from_start, 161 copy_size = Min(from->length() - from_start,
162 to->length() - to_start); 162 to->length() - to_start);
163 #ifdef DEBUG 163 #ifdef DEBUG
164 // FAST_*_ELEMENTS arrays cannot be uninitialized. Ensure they are already 164 // FAST_*_ELEMENTS arrays cannot be uninitialized. Ensure they are already
165 // marked with the hole. 165 // marked with the hole.
166 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { 166 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
167 for (int i = to_start + copy_size; i < to->length(); ++i) { 167 for (int i = to_start + copy_size; i < to->length(); ++i) {
168 ASSERT(to->get(i)->IsTheHole()); 168 ASSERT(to->get(i)->IsTheHole());
169 } 169 }
170 } 170 }
171 #endif 171 #endif
172 } 172 }
173 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && 173 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
174 (copy_size + static_cast<int>(from_start)) <= from->length()); 174 (copy_size + static_cast<int>(from_start)) <= from->length());
175 if (copy_size == 0) return; 175 if (copy_size == 0) return;
176 ASSERT(IsFastSmiOrObjectElementsKind(from_kind)); 176 ASSERT(IsFastSmiOrObjectElementsKind(from_kind));
177 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); 177 ASSERT(IsFastSmiOrObjectElementsKind(to_kind));
178 Address to_address = to->address() + FixedArray::kHeaderSize; 178 Address to_address = to->address() + FixedArray::kHeaderSize;
179 Address from_address = from->address() + FixedArray::kHeaderSize; 179 Address from_address = from->address() + FixedArray::kHeaderSize;
180 CopyWords(reinterpret_cast<Object**>(to_address) + to_start, 180 CopyWords(reinterpret_cast<Object**>(to_address) + to_start,
181 reinterpret_cast<Object**>(from_address) + from_start, 181 reinterpret_cast<Object**>(from_address) + from_start,
182 copy_size); 182 copy_size);
183 if (IsFastObjectElementsKind(from_kind) && 183 if (IsFastObjectElementsKind(from_kind) &&
184 IsFastObjectElementsKind(to_kind)) { 184 IsFastObjectElementsKind(to_kind)) {
185 Heap* heap = from->GetHeap(); 185 Heap* heap = from->GetHeap();
186 if (!heap->InNewSpace(to)) { 186 if (!heap->InNewSpace(to)) {
187 heap->RecordWrites(to->address(), 187 heap->RecordWrites(to->address(),
188 to->OffsetOfElementAt(to_start), 188 to->OffsetOfElementAt(to_start),
189 copy_size); 189 copy_size);
190 } 190 }
191 heap->incremental_marking()->RecordWrites(to); 191 heap->incremental_marking()->RecordWrites(to);
192 } 192 }
193 } 193 }
194 194
195 195
196 static void CopyDictionaryToObjectElements(SeededNumberDictionary* from, 196 static void CopyDictionaryToObjectElements(SeededNumberDictionary* from,
197 uint32_t from_start, 197 uint32_t from_start,
198 FixedArray* to, 198 FixedArray* to,
199 ElementsKind to_kind, 199 ElementsKind to_kind,
200 uint32_t to_start, 200 uint32_t to_start,
201 int raw_copy_size) { 201 int raw_copy_size) {
202 int copy_size = raw_copy_size; 202 int copy_size = raw_copy_size;
203 Heap* heap = from->GetHeap(); 203 Heap* heap = from->GetHeap();
204 if (raw_copy_size < 0) { 204 if (raw_copy_size < 0) {
205 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || 205 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
206 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); 206 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
207 copy_size = from->max_number_key() + 1 - from_start; 207 copy_size = from->max_number_key() + 1 - from_start;
208 #ifdef DEBUG 208 #ifdef DEBUG
209 // Fast object arrays cannot be uninitialized. Ensure they are already 209 // Fast object arrays cannot be uninitialized. Ensure they are already
210 // marked with the hole. 210 // marked with the hole.
211 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { 211 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
212 for (int i = to_start + copy_size; i < to->length(); ++i) { 212 for (int i = to_start + copy_size; i < to->length(); ++i) {
213 ASSERT(to->get(i)->IsTheHole()); 213 ASSERT(to->get(i)->IsTheHole());
214 } 214 }
215 } 215 }
216 #endif 216 #endif
217 } 217 }
218 ASSERT(to != from); 218 ASSERT(to != from);
219 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); 219 ASSERT(IsFastSmiOrObjectElementsKind(to_kind));
220 if (copy_size == 0) return; 220 if (copy_size == 0) return;
221 uint32_t to_length = to->length(); 221 uint32_t to_length = to->length();
222 if (to_start + copy_size > to_length) { 222 if (to_start + copy_size > to_length) {
223 copy_size = to_length - to_start; 223 copy_size = to_length - to_start;
224 } 224 }
225 for (int i = 0; i < copy_size; i++) { 225 for (int i = 0; i < copy_size; i++) {
226 int entry = from->FindEntry(i + from_start); 226 int entry = from->FindEntry(i + from_start);
227 if (entry != SeededNumberDictionary::kNotFound) { 227 if (entry != SeededNumberDictionary::kNotFound) {
228 Object* value = from->ValueAt(entry); 228 Object* value = from->ValueAt(entry);
229 ASSERT(!value->IsTheHole()); 229 ASSERT(!value->IsTheHole());
230 to->set(i + to_start, value, SKIP_WRITE_BARRIER); 230 to->set(i + to_start, value, SKIP_WRITE_BARRIER);
231 } else { 231 } else {
232 to->set_the_hole(i + to_start); 232 to->set_the_hole(i + to_start);
233 } 233 }
234 } 234 }
235 if (IsFastObjectElementsKind(to_kind)) { 235 if (IsFastObjectElementsKind(to_kind)) {
236 if (!heap->InNewSpace(to)) { 236 if (!heap->InNewSpace(to)) {
237 heap->RecordWrites(to->address(), 237 heap->RecordWrites(to->address(),
238 to->OffsetOfElementAt(to_start), 238 to->OffsetOfElementAt(to_start),
239 copy_size); 239 copy_size);
240 } 240 }
241 heap->incremental_marking()->RecordWrites(to); 241 heap->incremental_marking()->RecordWrites(to);
242 } 242 }
243 } 243 }
244 244
245 245
246 MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements( 246 MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements(
247 FixedDoubleArray* from, 247 FixedDoubleArray* from,
248 uint32_t from_start, 248 uint32_t from_start,
249 FixedArray* to, 249 FixedArray* to,
250 ElementsKind to_kind, 250 ElementsKind to_kind,
251 uint32_t to_start, 251 uint32_t to_start,
252 int raw_copy_size) { 252 int raw_copy_size) {
253 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); 253 ASSERT(IsFastSmiOrObjectElementsKind(to_kind));
254 int copy_size = raw_copy_size; 254 int copy_size = raw_copy_size;
255 if (raw_copy_size < 0) { 255 if (raw_copy_size < 0) {
256 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || 256 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
257 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); 257 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
258 copy_size = Min(from->length() - from_start, 258 copy_size = Min(from->length() - from_start,
259 to->length() - to_start); 259 to->length() - to_start);
260 #ifdef DEBUG 260 #ifdef DEBUG
261 // FAST_*_ELEMENTS arrays cannot be uninitialized. Ensure they are already 261 // FAST_*_ELEMENTS arrays cannot be uninitialized. Ensure they are already
262 // marked with the hole. 262 // marked with the hole.
263 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { 263 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
264 for (int i = to_start + copy_size; i < to->length(); ++i) { 264 for (int i = to_start + copy_size; i < to->length(); ++i) {
265 ASSERT(to->get(i)->IsTheHole()); 265 ASSERT(to->get(i)->IsTheHole());
266 } 266 }
267 } 267 }
268 #endif 268 #endif
269 } 269 }
270 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && 270 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
271 (copy_size + static_cast<int>(from_start)) <= from->length()); 271 (copy_size + static_cast<int>(from_start)) <= from->length());
272 if (copy_size == 0) return from; 272 if (copy_size == 0) return from;
273 for (int i = 0; i < copy_size; ++i) { 273 for (int i = 0; i < copy_size; ++i) {
274 if (IsFastSmiElementsKind(to_kind)) { 274 if (IsFastSmiElementsKind(to_kind)) {
275 UNIMPLEMENTED(); 275 UNIMPLEMENTED();
276 return Failure::Exception(); 276 return Failure::Exception();
277 } else { 277 } else {
278 MaybeObject* maybe_value = from->get(i + from_start); 278 MaybeObject* maybe_value = from->get(i + from_start);
279 Object* value; 279 Object* value;
280 ASSERT(IsFastObjectElementsKind(to_kind)); 280 ASSERT(IsFastObjectElementsKind(to_kind));
281 // Because Double -> Object elements transitions allocate HeapObjects 281 // Because Double -> Object elements transitions allocate HeapObjects
282 // iteratively, the allocate must succeed within a single GC cycle, 282 // iteratively, the allocate must succeed within a single GC cycle,
283 // otherwise the retry after the GC will also fail. In order to ensure 283 // otherwise the retry after the GC will also fail. In order to ensure
284 // that no GC is triggered, allocate HeapNumbers from old space if they 284 // that no GC is triggered, allocate HeapNumbers from old space if they
285 // can't be taken from new space. 285 // can't be taken from new space.
286 if (!maybe_value->ToObject(&value)) { 286 if (!maybe_value->ToObject(&value)) {
287 ASSERT(maybe_value->IsRetryAfterGC() || maybe_value->IsOutOfMemory()); 287 ASSERT(maybe_value->IsRetryAfterGC() || maybe_value->IsOutOfMemory());
288 Heap* heap = from->GetHeap(); 288 Heap* heap = from->GetHeap();
289 MaybeObject* maybe_value_object = 289 MaybeObject* maybe_value_object =
290 heap->AllocateHeapNumber(from->get_scalar(i + from_start), 290 heap->AllocateHeapNumber(from->get_scalar(i + from_start),
291 TENURED); 291 TENURED);
292 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; 292 if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
293 } 293 }
294 to->set(i + to_start, value, UPDATE_WRITE_BARRIER); 294 to->set(i + to_start, value, UPDATE_WRITE_BARRIER);
295 } 295 }
296 } 296 }
297 return to; 297 return to;
298 } 298 }
299 299
300 300
301 static void CopyDoubleToDoubleElements(FixedDoubleArray* from, 301 static void CopyDoubleToDoubleElements(FixedDoubleArray* from,
302 uint32_t from_start, 302 uint32_t from_start,
303 FixedDoubleArray* to, 303 FixedDoubleArray* to,
304 uint32_t to_start, 304 uint32_t to_start,
305 int raw_copy_size) { 305 int raw_copy_size) {
306 int copy_size = raw_copy_size; 306 int copy_size = raw_copy_size;
307 if (raw_copy_size < 0) { 307 if (raw_copy_size < 0) {
308 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || 308 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
309 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); 309 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
310 copy_size = Min(from->length() - from_start, 310 copy_size = Min(from->length() - from_start,
311 to->length() - to_start); 311 to->length() - to_start);
312 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { 312 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
313 for (int i = to_start + copy_size; i < to->length(); ++i) { 313 for (int i = to_start + copy_size; i < to->length(); ++i) {
314 to->set_the_hole(i); 314 to->set_the_hole(i);
315 } 315 }
316 } 316 }
317 } 317 }
318 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && 318 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
319 (copy_size + static_cast<int>(from_start)) <= from->length()); 319 (copy_size + static_cast<int>(from_start)) <= from->length());
320 if (copy_size == 0) return; 320 if (copy_size == 0) return;
321 Address to_address = to->address() + FixedDoubleArray::kHeaderSize; 321 Address to_address = to->address() + FixedDoubleArray::kHeaderSize;
322 Address from_address = from->address() + FixedDoubleArray::kHeaderSize; 322 Address from_address = from->address() + FixedDoubleArray::kHeaderSize;
323 to_address += kDoubleSize * to_start; 323 to_address += kDoubleSize * to_start;
324 from_address += kDoubleSize * from_start; 324 from_address += kDoubleSize * from_start;
325 int words_per_double = (kDoubleSize / kPointerSize); 325 int words_per_double = (kDoubleSize / kPointerSize);
326 CopyWords(reinterpret_cast<Object**>(to_address), 326 CopyWords(reinterpret_cast<Object**>(to_address),
327 reinterpret_cast<Object**>(from_address), 327 reinterpret_cast<Object**>(from_address),
328 words_per_double * copy_size); 328 words_per_double * copy_size);
329 } 329 }
330 330
331 331
332 static void CopySmiToDoubleElements(FixedArray* from, 332 static void CopySmiToDoubleElements(FixedArray* from,
333 uint32_t from_start, 333 uint32_t from_start,
334 FixedDoubleArray* to, 334 FixedDoubleArray* to,
335 uint32_t to_start, 335 uint32_t to_start,
336 int raw_copy_size) { 336 int raw_copy_size) {
337 int copy_size = raw_copy_size; 337 int copy_size = raw_copy_size;
338 if (raw_copy_size < 0) { 338 if (raw_copy_size < 0) {
339 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || 339 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
340 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); 340 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
341 copy_size = from->length() - from_start; 341 copy_size = from->length() - from_start;
342 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { 342 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
343 for (int i = to_start + copy_size; i < to->length(); ++i) { 343 for (int i = to_start + copy_size; i < to->length(); ++i) {
344 to->set_the_hole(i); 344 to->set_the_hole(i);
345 } 345 }
346 } 346 }
347 } 347 }
348 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && 348 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
349 (copy_size + static_cast<int>(from_start)) <= from->length()); 349 (copy_size + static_cast<int>(from_start)) <= from->length());
350 if (copy_size == 0) return; 350 if (copy_size == 0) return;
351 Object* the_hole = from->GetHeap()->the_hole_value(); 351 Object* the_hole = from->GetHeap()->the_hole_value();
352 for (uint32_t from_end = from_start + static_cast<uint32_t>(copy_size); 352 for (uint32_t from_end = from_start + static_cast<uint32_t>(copy_size);
353 from_start < from_end; from_start++, to_start++) { 353 from_start < from_end; from_start++, to_start++) {
354 Object* hole_or_smi = from->get(from_start); 354 Object* hole_or_smi = from->get(from_start);
355 if (hole_or_smi == the_hole) { 355 if (hole_or_smi == the_hole) {
356 to->set_the_hole(to_start); 356 to->set_the_hole(to_start);
357 } else { 357 } else {
358 to->set(to_start, Smi::cast(hole_or_smi)->value()); 358 to->set(to_start, Smi::cast(hole_or_smi)->value());
359 } 359 }
360 } 360 }
361 } 361 }
362 362
363 363
364 static void CopyPackedSmiToDoubleElements(FixedArray* from, 364 static void CopyPackedSmiToDoubleElements(FixedArray* from,
365 uint32_t from_start, 365 uint32_t from_start,
366 FixedDoubleArray* to, 366 FixedDoubleArray* to,
367 uint32_t to_start, 367 uint32_t to_start,
368 int packed_size, 368 int packed_size,
369 int raw_copy_size) { 369 int raw_copy_size) {
370 int copy_size = raw_copy_size; 370 int copy_size = raw_copy_size;
371 uint32_t to_end; 371 uint32_t to_end;
372 if (raw_copy_size < 0) { 372 if (raw_copy_size < 0) {
373 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || 373 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
374 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); 374 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
375 copy_size = from->length() - from_start; 375 copy_size = from->length() - from_start;
376 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { 376 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
377 to_end = to->length(); 377 to_end = to->length();
378 } else { 378 } else {
379 to_end = to_start + static_cast<uint32_t>(copy_size); 379 to_end = to_start + static_cast<uint32_t>(copy_size);
380 } 380 }
381 } else { 381 } else {
382 to_end = to_start + static_cast<uint32_t>(copy_size); 382 to_end = to_start + static_cast<uint32_t>(copy_size);
383 } 383 }
384 ASSERT(static_cast<int>(to_end) <= to->length()); 384 ASSERT(static_cast<int>(to_end) <= to->length());
385 ASSERT(packed_size >= 0 && packed_size <= copy_size); 385 ASSERT(packed_size >= 0 && packed_size <= copy_size);
386 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && 386 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
387 (copy_size + static_cast<int>(from_start)) <= from->length()); 387 (copy_size + static_cast<int>(from_start)) <= from->length());
388 if (copy_size == 0) return; 388 if (copy_size == 0) return;
389 for (uint32_t from_end = from_start + static_cast<uint32_t>(packed_size); 389 for (uint32_t from_end = from_start + static_cast<uint32_t>(packed_size);
390 from_start < from_end; from_start++, to_start++) { 390 from_start < from_end; from_start++, to_start++) {
391 Object* smi = from->get(from_start); 391 Object* smi = from->get(from_start);
392 ASSERT(!smi->IsTheHole()); 392 ASSERT(!smi->IsTheHole());
393 to->set(to_start, Smi::cast(smi)->value()); 393 to->set(to_start, Smi::cast(smi)->value());
394 } 394 }
395 395
396 while (to_start < to_end) { 396 while (to_start < to_end) {
397 to->set_the_hole(to_start++); 397 to->set_the_hole(to_start++);
398 } 398 }
399 } 399 }
400 400
401 401
402 static void CopyObjectToDoubleElements(FixedArray* from, 402 static void CopyObjectToDoubleElements(FixedArray* from,
403 uint32_t from_start, 403 uint32_t from_start,
404 FixedDoubleArray* to, 404 FixedDoubleArray* to,
405 uint32_t to_start, 405 uint32_t to_start,
406 int raw_copy_size) { 406 int raw_copy_size) {
407 int copy_size = raw_copy_size; 407 int copy_size = raw_copy_size;
408 if (raw_copy_size < 0) { 408 if (raw_copy_size < 0) {
409 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || 409 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
410 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); 410 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
411 copy_size = from->length() - from_start; 411 copy_size = from->length() - from_start;
412 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { 412 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
413 for (int i = to_start + copy_size; i < to->length(); ++i) { 413 for (int i = to_start + copy_size; i < to->length(); ++i) {
414 to->set_the_hole(i); 414 to->set_the_hole(i);
415 } 415 }
416 } 416 }
417 } 417 }
418 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && 418 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
419 (copy_size + static_cast<int>(from_start)) <= from->length()); 419 (copy_size + static_cast<int>(from_start)) <= from->length());
420 if (copy_size == 0) return; 420 if (copy_size == 0) return;
421 Object* the_hole = from->GetHeap()->the_hole_value(); 421 Object* the_hole = from->GetHeap()->the_hole_value();
422 for (uint32_t from_end = from_start + copy_size; 422 for (uint32_t from_end = from_start + copy_size;
423 from_start < from_end; from_start++, to_start++) { 423 from_start < from_end; from_start++, to_start++) {
424 Object* hole_or_object = from->get(from_start); 424 Object* hole_or_object = from->get(from_start);
425 if (hole_or_object == the_hole) { 425 if (hole_or_object == the_hole) {
426 to->set_the_hole(to_start); 426 to->set_the_hole(to_start);
427 } else { 427 } else {
428 to->set(to_start, hole_or_object->Number()); 428 to->set(to_start, hole_or_object->Number());
429 } 429 }
430 } 430 }
431 } 431 }
432 432
433 433
434 static void CopyDictionaryToDoubleElements(SeededNumberDictionary* from, 434 static void CopyDictionaryToDoubleElements(SeededNumberDictionary* from,
435 uint32_t from_start, 435 uint32_t from_start,
436 FixedDoubleArray* to, 436 FixedDoubleArray* to,
437 uint32_t to_start, 437 uint32_t to_start,
438 int raw_copy_size) { 438 int raw_copy_size) {
439 int copy_size = raw_copy_size; 439 int copy_size = raw_copy_size;
440 if (copy_size < 0) { 440 if (copy_size < 0) {
441 ASSERT(copy_size == ElementsAccessor::kCopyToEnd || 441 ASSERT(copy_size == ElementsAccessor::kCopyToEnd ||
442 copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); 442 copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
443 copy_size = from->max_number_key() + 1 - from_start; 443 copy_size = from->max_number_key() + 1 - from_start;
444 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { 444 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
445 for (int i = to_start + copy_size; i < to->length(); ++i) { 445 for (int i = to_start + copy_size; i < to->length(); ++i) {
446 to->set_the_hole(i); 446 to->set_the_hole(i);
447 } 447 }
448 } 448 }
449 } 449 }
450 if (copy_size == 0) return; 450 if (copy_size == 0) return;
451 uint32_t to_length = to->length(); 451 uint32_t to_length = to->length();
452 if (to_start + copy_size > to_length) { 452 if (to_start + copy_size > to_length) {
453 copy_size = to_length - to_start; 453 copy_size = to_length - to_start;
454 } 454 }
455 for (int i = 0; i < copy_size; i++) { 455 for (int i = 0; i < copy_size; i++) {
456 int entry = from->FindEntry(i + from_start); 456 int entry = from->FindEntry(i + from_start);
457 if (entry != SeededNumberDictionary::kNotFound) { 457 if (entry != SeededNumberDictionary::kNotFound) {
458 to->set(i + to_start, from->ValueAt(entry)->Number()); 458 to->set(i + to_start, from->ValueAt(entry)->Number());
459 } else { 459 } else {
460 to->set_the_hole(i + to_start); 460 to->set_the_hole(i + to_start);
461 } 461 }
462 } 462 }
463 } 463 }
464 464
465 465
466 // Base class for element handler implementations. Contains the 466 // Base class for element handler implementations. Contains the
467 // the common logic for objects with different ElementsKinds. 467 // the common logic for objects with different ElementsKinds.
468 // Subclasses must specialize method for which the element 468 // Subclasses must specialize method for which the element
469 // implementation differs from the base class implementation. 469 // implementation differs from the base class implementation.
470 // 470 //
471 // This class is intended to be used in the following way: 471 // This class is intended to be used in the following way:
472 // 472 //
473 // class SomeElementsAccessor : 473 // class SomeElementsAccessor :
474 // public ElementsAccessorBase<SomeElementsAccessor, 474 // public ElementsAccessorBase<SomeElementsAccessor,
475 // BackingStoreClass> { 475 // BackingStoreClass> {
476 // ... 476 // ...
477 // } 477 // }
478 // 478 //
479 // This is an example of the Curiously Recurring Template Pattern (see 479 // This is an example of the Curiously Recurring Template Pattern (see
480 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use 480 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use
481 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and 481 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and
482 // specialization of SomeElementsAccessor methods). 482 // specialization of SomeElementsAccessor methods).
483 template <typename ElementsAccessorSubclass, 483 template <typename ElementsAccessorSubclass,
484 typename ElementsTraitsParam> 484 typename ElementsTraitsParam>
485 class ElementsAccessorBase : public ElementsAccessor { 485 class ElementsAccessorBase : public ElementsAccessor {
486 protected: 486 protected:
487 explicit ElementsAccessorBase(const char* name) 487 explicit ElementsAccessorBase(const char* name)
488 : ElementsAccessor(name) { } 488 : ElementsAccessor(name) { }
489 489
490 typedef ElementsTraitsParam ElementsTraits; 490 typedef ElementsTraitsParam ElementsTraits;
491 typedef typename ElementsTraitsParam::BackingStore BackingStore; 491 typedef typename ElementsTraitsParam::BackingStore BackingStore;
492 492
493 virtual ElementsKind kind() const { return ElementsTraits::Kind; } 493 virtual ElementsKind kind() const { return ElementsTraits::Kind; }
494 494
495 static void ValidateContents(JSObject* holder, int length) { 495 static void ValidateContents(JSObject* holder, int length) {
496 } 496 }
497 497
498 static void ValidateImpl(JSObject* holder) { 498 static void ValidateImpl(JSObject* holder) {
499 FixedArrayBase* fixed_array_base = holder->elements(); 499 FixedArrayBase* fixed_array_base = holder->elements();
500 // When objects are first allocated, its elements are Failures. 500 // When objects are first allocated, its elements are Failures.
501 if (fixed_array_base->IsFailure()) return; 501 if (fixed_array_base->IsFailure()) return;
502 if (!fixed_array_base->IsHeapObject()) return; 502 if (!fixed_array_base->IsHeapObject()) return;
503 Map* map = fixed_array_base->map(); 503 Map* map = fixed_array_base->map();
504 // Arrays that have been shifted in place can't be verified. 504 // Arrays that have been shifted in place can't be verified.
505 Heap* heap = holder->GetHeap(); 505 Heap* heap = holder->GetHeap();
506 if (map == heap->raw_unchecked_one_pointer_filler_map() || 506 if (map == heap->raw_unchecked_one_pointer_filler_map() ||
507 map == heap->raw_unchecked_two_pointer_filler_map() || 507 map == heap->raw_unchecked_two_pointer_filler_map() ||
508 map == heap->free_space_map()) { 508 map == heap->free_space_map()) {
509 return; 509 return;
510 } 510 }
511 int length = 0; 511 int length = 0;
512 if (holder->IsJSArray()) { 512 if (holder->IsJSArray()) {
513 Object* length_obj = JSArray::cast(holder)->length(); 513 Object* length_obj = JSArray::cast(holder)->length();
514 if (length_obj->IsSmi()) { 514 if (length_obj->IsSmi()) {
515 length = Smi::cast(length_obj)->value(); 515 length = Smi::cast(length_obj)->value();
516 } 516 }
517 } else { 517 } else {
518 length = fixed_array_base->length(); 518 length = fixed_array_base->length();
519 } 519 }
520 ElementsAccessorSubclass::ValidateContents(holder, length); 520 ElementsAccessorSubclass::ValidateContents(holder, length);
521 } 521 }
522 522
523 virtual void Validate(JSObject* holder) { 523 virtual void Validate(JSObject* holder) {
524 ElementsAccessorSubclass::ValidateImpl(holder); 524 ElementsAccessorSubclass::ValidateImpl(holder);
525 } 525 }
526 526
527 static bool HasElementImpl(Object* receiver, 527 static bool HasElementImpl(Object* receiver,
528 JSObject* holder, 528 JSObject* holder,
529 uint32_t key, 529 uint32_t key,
530 BackingStore* backing_store) { 530 BackingStore* backing_store) {
531 MaybeObject* element = 531 MaybeObject* element =
532 ElementsAccessorSubclass::GetImpl(receiver, holder, key, backing_store); 532 ElementsAccessorSubclass::GetImpl(receiver, holder, key, backing_store);
533 return !element->IsTheHole(); 533 return !element->IsTheHole();
534 } 534 }
535 535
536 virtual bool HasElement(Object* receiver, 536 virtual bool HasElement(Object* receiver,
537 JSObject* holder, 537 JSObject* holder,
538 uint32_t key, 538 uint32_t key,
539 FixedArrayBase* backing_store) { 539 FixedArrayBase* backing_store) {
540 if (backing_store == NULL) { 540 if (backing_store == NULL) {
541 backing_store = holder->elements(); 541 backing_store = holder->elements();
542 } 542 }
543 return ElementsAccessorSubclass::HasElementImpl( 543 return ElementsAccessorSubclass::HasElementImpl(
544 receiver, holder, key, BackingStore::cast(backing_store)); 544 receiver, holder, key, BackingStore::cast(backing_store));
545 } 545 }
546 546
547 MUST_USE_RESULT virtual MaybeObject* Get(Object* receiver, 547 MUST_USE_RESULT virtual MaybeObject* Get(Object* receiver,
548 JSObject* holder, 548 JSObject* holder,
549 uint32_t key, 549 uint32_t key,
550 FixedArrayBase* backing_store) { 550 FixedArrayBase* backing_store) {
551 if (backing_store == NULL) { 551 if (backing_store == NULL) {
552 backing_store = holder->elements(); 552 backing_store = holder->elements();
553 } 553 }
554 return ElementsAccessorSubclass::GetImpl( 554 return ElementsAccessorSubclass::GetImpl(
555 receiver, holder, key, BackingStore::cast(backing_store)); 555 receiver, holder, key, BackingStore::cast(backing_store));
556 } 556 }
557 557
558 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, 558 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver,
559 JSObject* obj, 559 JSObject* obj,
560 uint32_t key, 560 uint32_t key,
561 BackingStore* backing_store) { 561 BackingStore* backing_store) {
562 return (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store)) 562 return (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store))
563 ? backing_store->get(key) 563 ? backing_store->get(key)
564 : backing_store->GetHeap()->the_hole_value(); 564 : backing_store->GetHeap()->the_hole_value();
565 } 565 }
566 566
567 MUST_USE_RESULT virtual MaybeObject* SetLength(JSArray* array, 567 MUST_USE_RESULT virtual MaybeObject* SetLength(JSArray* array,
568 Object* length) { 568 Object* length) {
569 return ElementsAccessorSubclass::SetLengthImpl( 569 return ElementsAccessorSubclass::SetLengthImpl(
570 array, length, BackingStore::cast(array->elements())); 570 array, length, BackingStore::cast(array->elements()));
571 } 571 }
572 572
573 MUST_USE_RESULT static MaybeObject* SetLengthImpl( 573 MUST_USE_RESULT static MaybeObject* SetLengthImpl(
574 JSObject* obj, 574 JSObject* obj,
575 Object* length, 575 Object* length,
576 BackingStore* backing_store); 576 BackingStore* backing_store);
577 577
578 MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength( 578 MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength(
579 JSArray* array, 579 JSArray* array,
580 int capacity, 580 int capacity,
581 int length) { 581 int length) {
582 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( 582 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength(
583 array, 583 array,
584 capacity, 584 capacity,
585 length); 585 length);
586 } 586 }
587 587
588 MUST_USE_RESULT static MaybeObject* SetFastElementsCapacityAndLength( 588 MUST_USE_RESULT static MaybeObject* SetFastElementsCapacityAndLength(
589 JSObject* obj, 589 JSObject* obj,
590 int capacity, 590 int capacity,
591 int length) { 591 int length) {
592 UNIMPLEMENTED(); 592 UNIMPLEMENTED();
593 return obj; 593 return obj;
594 } 594 }
595 595
596 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, 596 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj,
597 uint32_t key, 597 uint32_t key,
598 JSReceiver::DeleteMode mode) = 0; 598 JSReceiver::DeleteMode mode) = 0;
599 599
600 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, 600 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
601 uint32_t from_start, 601 uint32_t from_start,
602 FixedArrayBase* to, 602 FixedArrayBase* to,
603 ElementsKind to_kind, 603 ElementsKind to_kind,
604 uint32_t to_start, 604 uint32_t to_start,
605 int packed_size, 605 int packed_size,
606 int copy_size) { 606 int copy_size) {
607 UNREACHABLE(); 607 UNREACHABLE();
608 return NULL; 608 return NULL;
609 } 609 }
610 610
611 MUST_USE_RESULT virtual MaybeObject* CopyElements(JSObject* from_holder, 611 MUST_USE_RESULT virtual MaybeObject* CopyElements(JSObject* from_holder,
612 uint32_t from_start, 612 uint32_t from_start,
613 FixedArrayBase* to, 613 FixedArrayBase* to,
614 ElementsKind to_kind, 614 ElementsKind to_kind,
615 uint32_t to_start, 615 uint32_t to_start,
616 int copy_size, 616 int copy_size,
617 FixedArrayBase* from) { 617 FixedArrayBase* from) {
618 int packed_size = kPackedSizeNotKnown; 618 int packed_size = kPackedSizeNotKnown;
619 if (from == NULL) { 619 if (from == NULL) {
620 from = from_holder->elements(); 620 from = from_holder->elements();
621 } 621 }
622 622
623 if (from_holder) { 623 if (from_holder) {
624 ElementsKind elements_kind = from_holder->GetElementsKind(); 624 ElementsKind elements_kind = from_holder->GetElementsKind();
625 bool is_packed = IsFastPackedElementsKind(elements_kind) && 625 bool is_packed = IsFastPackedElementsKind(elements_kind) &&
626 from_holder->IsJSArray(); 626 from_holder->IsJSArray();
627 if (is_packed) { 627 if (is_packed) {
628 packed_size = Smi::cast(JSArray::cast(from_holder)->length())->value(); 628 packed_size = Smi::cast(JSArray::cast(from_holder)->length())->value();
629 if (copy_size >= 0 && packed_size > copy_size) { 629 if (copy_size >= 0 && packed_size > copy_size) {
630 packed_size = copy_size; 630 packed_size = copy_size;
631 } 631 }
632 } 632 }
633 } 633 }
634 if (from->length() == 0) { 634 if (from->length() == 0) {
635 return from; 635 return from;
636 } 636 }
637 return ElementsAccessorSubclass::CopyElementsImpl( 637 return ElementsAccessorSubclass::CopyElementsImpl(
638 from, from_start, to, to_kind, to_start, packed_size, copy_size); 638 from, from_start, to, to_kind, to_start, packed_size, copy_size);
639 } 639 }
640 640
641 MUST_USE_RESULT virtual MaybeObject* AddElementsToFixedArray( 641 MUST_USE_RESULT virtual MaybeObject* AddElementsToFixedArray(
642 Object* receiver, 642 Object* receiver,
643 JSObject* holder, 643 JSObject* holder,
644 FixedArray* to, 644 FixedArray* to,
645 FixedArrayBase* from) { 645 FixedArrayBase* from) {
646 int len0 = to->length(); 646 int len0 = to->length();
647 #ifdef DEBUG 647 #ifdef DEBUG
648 if (FLAG_enable_slow_asserts) { 648 if (FLAG_enable_slow_asserts) {
649 for (int i = 0; i < len0; i++) { 649 for (int i = 0; i < len0; i++) {
650 ASSERT(!to->get(i)->IsTheHole()); 650 ASSERT(!to->get(i)->IsTheHole());
651 } 651 }
652 } 652 }
653 #endif 653 #endif
654 if (from == NULL) { 654 if (from == NULL) {
655 from = holder->elements(); 655 from = holder->elements();
656 } 656 }
657 BackingStore* backing_store = BackingStore::cast(from); 657 BackingStore* backing_store = BackingStore::cast(from);
658 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(backing_store); 658 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(backing_store);
659 659
660 // Optimize if 'other' is empty. 660 // Optimize if 'other' is empty.
661 // We cannot optimize if 'this' is empty, as other may have holes. 661 // We cannot optimize if 'this' is empty, as other may have holes.
662 if (len1 == 0) return to; 662 if (len1 == 0) return to;
663 663
664 // Compute how many elements are not in other. 664 // Compute how many elements are not in other.
665 uint32_t extra = 0; 665 uint32_t extra = 0;
666 for (uint32_t y = 0; y < len1; y++) { 666 for (uint32_t y = 0; y < len1; y++) {
667 uint32_t key = 667 uint32_t key =
668 ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y); 668 ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y);
669 if (ElementsAccessorSubclass::HasElementImpl( 669 if (ElementsAccessorSubclass::HasElementImpl(
670 receiver, holder, key, backing_store)) { 670 receiver, holder, key, backing_store)) {
671 MaybeObject* maybe_value = 671 MaybeObject* maybe_value =
672 ElementsAccessorSubclass::GetImpl(receiver, holder, 672 ElementsAccessorSubclass::GetImpl(receiver, holder,
673 key, backing_store); 673 key, backing_store);
674 Object* value; 674 Object* value;
675 if (!maybe_value->ToObject(&value)) return maybe_value; 675 if (!maybe_value->ToObject(&value)) return maybe_value;
676 ASSERT(!value->IsTheHole()); 676 ASSERT(!value->IsTheHole());
677 if (!HasKey(to, value)) { 677 if (!HasKey(to, value)) {
678 extra++; 678 extra++;
679 } 679 }
680 } 680 }
681 } 681 }
682 682
683 if (extra == 0) return to; 683 if (extra == 0) return to;
684 684
685 // Allocate the result 685 // Allocate the result
686 FixedArray* result; 686 FixedArray* result;
687 MaybeObject* maybe_obj = 687 MaybeObject* maybe_obj =
688 backing_store->GetHeap()->AllocateFixedArray(len0 + extra); 688 backing_store->GetHeap()->AllocateFixedArray(len0 + extra);
689 if (!maybe_obj->To<FixedArray>(&result)) return maybe_obj; 689 if (!maybe_obj->To<FixedArray>(&result)) return maybe_obj;
690 690
691 // Fill in the content 691 // Fill in the content
692 { 692 {
693 AssertNoAllocation no_gc; 693 AssertNoAllocation no_gc;
694 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); 694 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
695 for (int i = 0; i < len0; i++) { 695 for (int i = 0; i < len0; i++) {
696 Object* e = to->get(i); 696 Object* e = to->get(i);
697 ASSERT(e->IsString() || e->IsNumber()); 697 ASSERT(e->IsString() || e->IsNumber());
698 result->set(i, e, mode); 698 result->set(i, e, mode);
699 } 699 }
700 } 700 }
701 // Fill in the extra values. 701 // Fill in the extra values.
702 uint32_t index = 0; 702 uint32_t index = 0;
703 for (uint32_t y = 0; y < len1; y++) { 703 for (uint32_t y = 0; y < len1; y++) {
704 uint32_t key = 704 uint32_t key =
705 ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y); 705 ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y);
706 if (ElementsAccessorSubclass::HasElementImpl( 706 if (ElementsAccessorSubclass::HasElementImpl(
707 receiver, holder, key, backing_store)) { 707 receiver, holder, key, backing_store)) {
708 MaybeObject* maybe_value = 708 MaybeObject* maybe_value =
709 ElementsAccessorSubclass::GetImpl(receiver, holder, 709 ElementsAccessorSubclass::GetImpl(receiver, holder,
710 key, backing_store); 710 key, backing_store);
711 Object* value; 711 Object* value;
712 if (!maybe_value->ToObject(&value)) return maybe_value; 712 if (!maybe_value->ToObject(&value)) return maybe_value;
713 if (!value->IsTheHole() && !HasKey(to, value)) { 713 if (!value->IsTheHole() && !HasKey(to, value)) {
714 result->set(len0 + index, value); 714 result->set(len0 + index, value);
715 index++; 715 index++;
716 } 716 }
717 } 717 }
718 } 718 }
719 ASSERT(extra == index); 719 ASSERT(extra == index);
720 return result; 720 return result;
721 } 721 }
722 722
723 protected: 723 protected:
724 static uint32_t GetCapacityImpl(BackingStore* backing_store) { 724 static uint32_t GetCapacityImpl(BackingStore* backing_store) {
725 return backing_store->length(); 725 return backing_store->length();
726 } 726 }
727 727
728 virtual uint32_t GetCapacity(FixedArrayBase* backing_store) { 728 virtual uint32_t GetCapacity(FixedArrayBase* backing_store) {
729 return ElementsAccessorSubclass::GetCapacityImpl( 729 return ElementsAccessorSubclass::GetCapacityImpl(
730 BackingStore::cast(backing_store)); 730 BackingStore::cast(backing_store));
731 } 731 }
732 732
733 static uint32_t GetKeyForIndexImpl(BackingStore* backing_store, 733 static uint32_t GetKeyForIndexImpl(BackingStore* backing_store,
734 uint32_t index) { 734 uint32_t index) {
735 return index; 735 return index;
736 } 736 }
737 737
738 virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, 738 virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store,
739 uint32_t index) { 739 uint32_t index) {
740 return ElementsAccessorSubclass::GetKeyForIndexImpl( 740 return ElementsAccessorSubclass::GetKeyForIndexImpl(
741 BackingStore::cast(backing_store), index); 741 BackingStore::cast(backing_store), index);
742 } 742 }
743 743
744 private: 744 private:
745 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); 745 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase);
746 }; 746 };
747 747
748 748
749 // Super class for all fast element arrays. 749 // Super class for all fast element arrays.
750 template<typename FastElementsAccessorSubclass, 750 template<typename FastElementsAccessorSubclass,
751 typename KindTraits, 751 typename KindTraits,
752 int ElementSize> 752 int ElementSize>
753 class FastElementsAccessor 753 class FastElementsAccessor
754 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { 754 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> {
755 public: 755 public:
756 explicit FastElementsAccessor(const char* name) 756 explicit FastElementsAccessor(const char* name)
757 : ElementsAccessorBase<FastElementsAccessorSubclass, 757 : ElementsAccessorBase<FastElementsAccessorSubclass,
758 KindTraits>(name) {} 758 KindTraits>(name) {}
759 protected: 759 protected:
760 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; 760 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>;
761 friend class NonStrictArgumentsElementsAccessor; 761 friend class NonStrictArgumentsElementsAccessor;
762 762
763 typedef typename KindTraits::BackingStore BackingStore; 763 typedef typename KindTraits::BackingStore BackingStore;
764 764
765 // Adjusts the length of the fast backing store or returns the new length or 765 // Adjusts the length of the fast backing store or returns the new length or
766 // undefined in case conversion to a slow backing store should be performed. 766 // undefined in case conversion to a slow backing store should be performed.
767 static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store, 767 static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store,
768 JSArray* array, 768 JSArray* array,
769 Object* length_object, 769 Object* length_object,
770 uint32_t length) { 770 uint32_t length) {
771 uint32_t old_capacity = backing_store->length(); 771 uint32_t old_capacity = backing_store->length();
772 Object* old_length = array->length(); 772 Object* old_length = array->length();
773 bool same_size = old_length->IsSmi() && 773 bool same_size = old_length->IsSmi() &&
774 static_cast<uint32_t>(Smi::cast(old_length)->value()) == length; 774 static_cast<uint32_t>(Smi::cast(old_length)->value()) == length;
775 ElementsKind kind = array->GetElementsKind(); 775 ElementsKind kind = array->GetElementsKind();
776 776
777 if (!same_size && IsFastElementsKind(kind) && 777 if (!same_size && IsFastElementsKind(kind) &&
778 !IsFastHoleyElementsKind(kind)) { 778 !IsFastHoleyElementsKind(kind)) {
779 kind = GetHoleyElementsKind(kind); 779 kind = GetHoleyElementsKind(kind);
780 MaybeObject* maybe_obj = array->TransitionElementsKind(kind); 780 MaybeObject* maybe_obj = array->TransitionElementsKind(kind);
781 if (maybe_obj->IsFailure()) return maybe_obj; 781 if (maybe_obj->IsFailure()) return maybe_obj;
782 } 782 }
783 783
784 // Check whether the backing store should be shrunk. 784 // Check whether the backing store should be shrunk.
785 if (length <= old_capacity) { 785 if (length <= old_capacity) {
786 if (array->HasFastSmiOrObjectElements()) { 786 if (array->HasFastSmiOrObjectElements()) {
787 MaybeObject* maybe_obj = array->EnsureWritableFastElements(); 787 MaybeObject* maybe_obj = array->EnsureWritableFastElements();
788 if (!maybe_obj->To(&backing_store)) return maybe_obj; 788 if (!maybe_obj->To(&backing_store)) return maybe_obj;
789 } 789 }
790 if (2 * length <= old_capacity) { 790 if (2 * length <= old_capacity) {
791 // If more than half the elements won't be used, trim the array. 791 // If more than half the elements won't be used, trim the array.
792 if (length == 0) { 792 if (length == 0) {
793 array->initialize_elements(); 793 array->initialize_elements();
794 } else { 794 } else {
795 backing_store->set_length(length); 795 backing_store->set_length(length);
796 Address filler_start = backing_store->address() + 796 Address filler_start = backing_store->address() +
797 BackingStore::OffsetOfElementAt(length); 797 BackingStore::OffsetOfElementAt(length);
798 int filler_size = (old_capacity - length) * ElementSize; 798 int filler_size = (old_capacity - length) * ElementSize;
799 array->GetHeap()->CreateFillerObjectAt(filler_start, filler_size); 799 array->GetHeap()->CreateFillerObjectAt(filler_start, filler_size);
800 } 800 }
801 } else { 801 } else {
802 // Otherwise, fill the unused tail with holes. 802 // Otherwise, fill the unused tail with holes.
803 int old_length = FastD2IChecked(array->length()->Number()); 803 int old_length = FastD2IChecked(array->length()->Number());
804 for (int i = length; i < old_length; i++) { 804 for (int i = length; i < old_length; i++) {
805 backing_store->set_the_hole(i); 805 backing_store->set_the_hole(i);
806 } 806 }
807 } 807 }
808 return length_object; 808 return length_object;
809 } 809 }
810 810
811 // Check whether the backing store should be expanded. 811 // Check whether the backing store should be expanded.
812 uint32_t min = JSObject::NewElementsCapacity(old_capacity); 812 uint32_t min = JSObject::NewElementsCapacity(old_capacity);
813 uint32_t new_capacity = length > min ? length : min; 813 uint32_t new_capacity = length > min ? length : min;
814 if (!array->ShouldConvertToSlowElements(new_capacity)) { 814 if (!array->ShouldConvertToSlowElements(new_capacity)) {
815 MaybeObject* result = FastElementsAccessorSubclass:: 815 MaybeObject* result = FastElementsAccessorSubclass::
816 SetFastElementsCapacityAndLength(array, new_capacity, length); 816 SetFastElementsCapacityAndLength(array, new_capacity, length);
817 if (result->IsFailure()) return result; 817 if (result->IsFailure()) return result;
818 array->ValidateElements(); 818 array->ValidateElements();
819 return length_object; 819 return length_object;
820 } 820 }
821 821
822 // Request conversion to slow elements. 822 // Request conversion to slow elements.
823 return array->GetHeap()->undefined_value(); 823 return array->GetHeap()->undefined_value();
824 } 824 }
825 825
826 static MaybeObject* DeleteCommon(JSObject* obj, 826 static MaybeObject* DeleteCommon(JSObject* obj,
827 uint32_t key, 827 uint32_t key,
828 JSReceiver::DeleteMode mode) { 828 JSReceiver::DeleteMode mode) {
829 ASSERT(obj->HasFastSmiOrObjectElements() || 829 ASSERT(obj->HasFastSmiOrObjectElements() ||
830 obj->HasFastDoubleElements() || 830 obj->HasFastDoubleElements() ||
831 obj->HasFastArgumentsElements()); 831 obj->HasFastArgumentsElements());
832 typename KindTraits::BackingStore* backing_store = 832 typename KindTraits::BackingStore* backing_store =
833 KindTraits::BackingStore::cast(obj->elements()); 833 KindTraits::BackingStore::cast(obj->elements());
834 Heap* heap = obj->GetHeap(); 834 Heap* heap = obj->GetHeap();
835 if (backing_store->map() == heap->non_strict_arguments_elements_map()) { 835 if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
836 backing_store = 836 backing_store =
837 KindTraits::BackingStore::cast( 837 KindTraits::BackingStore::cast(
838 FixedArray::cast(backing_store)->get(1)); 838 FixedArray::cast(backing_store)->get(1));
839 } else { 839 } else {
840 ElementsKind kind = KindTraits::Kind; 840 ElementsKind kind = KindTraits::Kind;
841 if (IsFastPackedElementsKind(kind)) { 841 if (IsFastPackedElementsKind(kind)) {
842 MaybeObject* transitioned = 842 MaybeObject* transitioned =
843 obj->TransitionElementsKind(GetHoleyElementsKind(kind)); 843 obj->TransitionElementsKind(GetHoleyElementsKind(kind));
844 if (transitioned->IsFailure()) return transitioned; 844 if (transitioned->IsFailure()) return transitioned;
845 } 845 }
846 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) { 846 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) {
847 Object* writable; 847 Object* writable;
848 MaybeObject* maybe = obj->EnsureWritableFastElements(); 848 MaybeObject* maybe = obj->EnsureWritableFastElements();
849 if (!maybe->ToObject(&writable)) return maybe; 849 if (!maybe->ToObject(&writable)) return maybe;
850 backing_store = KindTraits::BackingStore::cast(writable); 850 backing_store = KindTraits::BackingStore::cast(writable);
851 } 851 }
852 } 852 }
853 uint32_t length = static_cast<uint32_t>( 853 uint32_t length = static_cast<uint32_t>(
854 obj->IsJSArray() 854 obj->IsJSArray()
855 ? Smi::cast(JSArray::cast(obj)->length())->value() 855 ? Smi::cast(JSArray::cast(obj)->length())->value()
856 : backing_store->length()); 856 : backing_store->length());
857 if (key < length) { 857 if (key < length) {
858 backing_store->set_the_hole(key); 858 backing_store->set_the_hole(key);
859 // If an old space backing store is larger than a certain size and 859 // If an old space backing store is larger than a certain size and
860 // has too few used values, normalize it. 860 // has too few used values, normalize it.
861 // To avoid doing the check on every delete we require at least 861 // To avoid doing the check on every delete we require at least
862 // one adjacent hole to the value being deleted. 862 // one adjacent hole to the value being deleted.
863 const int kMinLengthForSparsenessCheck = 64; 863 const int kMinLengthForSparsenessCheck = 64;
864 if (backing_store->length() >= kMinLengthForSparsenessCheck && 864 if (backing_store->length() >= kMinLengthForSparsenessCheck &&
865 !heap->InNewSpace(backing_store) && 865 !heap->InNewSpace(backing_store) &&
866 ((key > 0 && backing_store->is_the_hole(key - 1)) || 866 ((key > 0 && backing_store->is_the_hole(key - 1)) ||
867 (key + 1 < length && backing_store->is_the_hole(key + 1)))) { 867 (key + 1 < length && backing_store->is_the_hole(key + 1)))) {
868 int num_used = 0; 868 int num_used = 0;
869 for (int i = 0; i < backing_store->length(); ++i) { 869 for (int i = 0; i < backing_store->length(); ++i) {
870 if (!backing_store->is_the_hole(i)) ++num_used; 870 if (!backing_store->is_the_hole(i)) ++num_used;
871 // Bail out early if more than 1/4 is used. 871 // Bail out early if more than 1/4 is used.
872 if (4 * num_used > backing_store->length()) break; 872 if (4 * num_used > backing_store->length()) break;
873 } 873 }
874 if (4 * num_used <= backing_store->length()) { 874 if (4 * num_used <= backing_store->length()) {
875 MaybeObject* result = obj->NormalizeElements(); 875 MaybeObject* result = obj->NormalizeElements();
876 if (result->IsFailure()) return result; 876 if (result->IsFailure()) return result;
877 } 877 }
878 } 878 }
879 } 879 }
880 return heap->true_value(); 880 return heap->true_value();
881 } 881 }
882 882
883 virtual MaybeObject* Delete(JSObject* obj, 883 virtual MaybeObject* Delete(JSObject* obj,
884 uint32_t key, 884 uint32_t key,
885 JSReceiver::DeleteMode mode) { 885 JSReceiver::DeleteMode mode) {
886 return DeleteCommon(obj, key, mode); 886 return DeleteCommon(obj, key, mode);
887 } 887 }
888 888
889 static bool HasElementImpl( 889 static bool HasElementImpl(
890 Object* receiver, 890 Object* receiver,
891 JSObject* holder, 891 JSObject* holder,
892 uint32_t key, 892 uint32_t key,
893 typename KindTraits::BackingStore* backing_store) { 893 typename KindTraits::BackingStore* backing_store) {
894 if (key >= static_cast<uint32_t>(backing_store->length())) { 894 if (key >= static_cast<uint32_t>(backing_store->length())) {
895 return false; 895 return false;
896 } 896 }
897 return !backing_store->is_the_hole(key); 897 return !backing_store->is_the_hole(key);
898 } 898 }
899 899
900 static void ValidateContents(JSObject* holder, int length) { 900 static void ValidateContents(JSObject* holder, int length) {
901 #if DEBUG 901 #if DEBUG
902 FixedArrayBase* elements = holder->elements(); 902 FixedArrayBase* elements = holder->elements();
903 Heap* heap = elements->GetHeap(); 903 Heap* heap = elements->GetHeap();
904 Map* map = elements->map(); 904 Map* map = elements->map();
905 ASSERT((IsFastSmiOrObjectElementsKind(KindTraits::Kind) && 905 ASSERT((IsFastSmiOrObjectElementsKind(KindTraits::Kind) &&
906 (map == heap->fixed_array_map() || 906 (map == heap->fixed_array_map() ||
907 map == heap->fixed_cow_array_map())) || 907 map == heap->fixed_cow_array_map())) ||
908 (IsFastDoubleElementsKind(KindTraits::Kind) == 908 (IsFastDoubleElementsKind(KindTraits::Kind) ==
909 ((map == heap->fixed_array_map() && length == 0) || 909 ((map == heap->fixed_array_map() && length == 0) ||
910 map == heap->fixed_double_array_map()))); 910 map == heap->fixed_double_array_map())));
911 for (int i = 0; i < length; i++) { 911 for (int i = 0; i < length; i++) {
912 typename KindTraits::BackingStore* backing_store = 912 typename KindTraits::BackingStore* backing_store =
913 KindTraits::BackingStore::cast(elements); 913 KindTraits::BackingStore::cast(elements);
914 ASSERT((!IsFastSmiElementsKind(KindTraits::Kind) || 914 ASSERT((!IsFastSmiElementsKind(KindTraits::Kind) ||
915 static_cast<Object*>(backing_store->get(i))->IsSmi()) || 915 static_cast<Object*>(backing_store->get(i))->IsSmi()) ||
916 (IsFastHoleyElementsKind(KindTraits::Kind) == 916 (IsFastHoleyElementsKind(KindTraits::Kind) ==
917 backing_store->is_the_hole(i))); 917 backing_store->is_the_hole(i)));
918 } 918 }
919 #endif 919 #endif
920 } 920 }
921 }; 921 };
922 922
923 923
924 template<typename FastElementsAccessorSubclass, 924 template<typename FastElementsAccessorSubclass,
925 typename KindTraits> 925 typename KindTraits>
926 class FastSmiOrObjectElementsAccessor 926 class FastSmiOrObjectElementsAccessor
927 : public FastElementsAccessor<FastElementsAccessorSubclass, 927 : public FastElementsAccessor<FastElementsAccessorSubclass,
928 KindTraits, 928 KindTraits,
929 kPointerSize> { 929 kPointerSize> {
930 public: 930 public:
931 explicit FastSmiOrObjectElementsAccessor(const char* name) 931 explicit FastSmiOrObjectElementsAccessor(const char* name)
932 : FastElementsAccessor<FastElementsAccessorSubclass, 932 : FastElementsAccessor<FastElementsAccessorSubclass,
933 KindTraits, 933 KindTraits,
934 kPointerSize>(name) {} 934 kPointerSize>(name) {}
935 935
936 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, 936 static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
937 uint32_t from_start, 937 uint32_t from_start,
938 FixedArrayBase* to, 938 FixedArrayBase* to,
939 ElementsKind to_kind, 939 ElementsKind to_kind,
940 uint32_t to_start, 940 uint32_t to_start,
941 int packed_size, 941 int packed_size,
942 int copy_size) { 942 int copy_size) {
943 if (IsFastSmiOrObjectElementsKind(to_kind)) { 943 if (IsFastSmiOrObjectElementsKind(to_kind)) {
944 CopyObjectToObjectElements( 944 CopyObjectToObjectElements(
945 FixedArray::cast(from), KindTraits::Kind, from_start, 945 FixedArray::cast(from), KindTraits::Kind, from_start,
946 FixedArray::cast(to), to_kind, to_start, copy_size); 946 FixedArray::cast(to), to_kind, to_start, copy_size);
947 } else if (IsFastDoubleElementsKind(to_kind)) { 947 } else if (IsFastDoubleElementsKind(to_kind)) {
948 if (IsFastSmiElementsKind(KindTraits::Kind)) { 948 if (IsFastSmiElementsKind(KindTraits::Kind)) {
949 if (IsFastPackedElementsKind(KindTraits::Kind) && 949 if (IsFastPackedElementsKind(KindTraits::Kind) &&
950 packed_size != kPackedSizeNotKnown) { 950 packed_size != kPackedSizeNotKnown) {
951 CopyPackedSmiToDoubleElements( 951 CopyPackedSmiToDoubleElements(
952 FixedArray::cast(from), from_start, 952 FixedArray::cast(from), from_start,
953 FixedDoubleArray::cast(to), to_start, 953 FixedDoubleArray::cast(to), to_start,
954 packed_size, copy_size); 954 packed_size, copy_size);
955 } else { 955 } else {
956 CopySmiToDoubleElements( 956 CopySmiToDoubleElements(
957 FixedArray::cast(from), from_start, 957 FixedArray::cast(from), from_start,
958 FixedDoubleArray::cast(to), to_start, copy_size); 958 FixedDoubleArray::cast(to), to_start, copy_size);
959 } 959 }
960 } else { 960 } else {
961 CopyObjectToDoubleElements( 961 CopyObjectToDoubleElements(
962 FixedArray::cast(from), from_start, 962 FixedArray::cast(from), from_start,
963 FixedDoubleArray::cast(to), to_start, copy_size); 963 FixedDoubleArray::cast(to), to_start, copy_size);
964 } 964 }
965 } else { 965 } else {
966 UNREACHABLE(); 966 UNREACHABLE();
967 } 967 }
968 return to->GetHeap()->undefined_value(); 968 return to->GetHeap()->undefined_value();
969 } 969 }
970 970
971 971
972 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, 972 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj,
973 uint32_t capacity, 973 uint32_t capacity,
974 uint32_t length) { 974 uint32_t length) {
975 JSObject::SetFastElementsCapacitySmiMode set_capacity_mode = 975 JSObject::SetFastElementsCapacitySmiMode set_capacity_mode =
976 obj->HasFastSmiElements() 976 obj->HasFastSmiElements()
977 ? JSObject::kAllowSmiElements 977 ? JSObject::kAllowSmiElements
978 : JSObject::kDontAllowSmiElements; 978 : JSObject::kDontAllowSmiElements;
979 return obj->SetFastElementsCapacityAndLength(capacity, 979 return obj->SetFastElementsCapacityAndLength(capacity,
980 length, 980 length,
981 set_capacity_mode); 981 set_capacity_mode);
982 } 982 }
983 }; 983 };
984 984
985 985
986 class FastPackedSmiElementsAccessor 986 class FastPackedSmiElementsAccessor
987 : public FastSmiOrObjectElementsAccessor< 987 : public FastSmiOrObjectElementsAccessor<
988 FastPackedSmiElementsAccessor, 988 FastPackedSmiElementsAccessor,
989 ElementsKindTraits<FAST_SMI_ELEMENTS> > { 989 ElementsKindTraits<FAST_SMI_ELEMENTS> > {
990 public: 990 public:
991 explicit FastPackedSmiElementsAccessor(const char* name) 991 explicit FastPackedSmiElementsAccessor(const char* name)
992 : FastSmiOrObjectElementsAccessor< 992 : FastSmiOrObjectElementsAccessor<
993 FastPackedSmiElementsAccessor, 993 FastPackedSmiElementsAccessor,
994 ElementsKindTraits<FAST_SMI_ELEMENTS> >(name) {} 994 ElementsKindTraits<FAST_SMI_ELEMENTS> >(name) {}
995 }; 995 };
996 996
997 997
998 class FastHoleySmiElementsAccessor 998 class FastHoleySmiElementsAccessor
999 : public FastSmiOrObjectElementsAccessor< 999 : public FastSmiOrObjectElementsAccessor<
1000 FastHoleySmiElementsAccessor, 1000 FastHoleySmiElementsAccessor,
1001 ElementsKindTraits<FAST_HOLEY_SMI_ELEMENTS> > { 1001 ElementsKindTraits<FAST_HOLEY_SMI_ELEMENTS> > {
1002 public: 1002 public:
1003 explicit FastHoleySmiElementsAccessor(const char* name) 1003 explicit FastHoleySmiElementsAccessor(const char* name)
1004 : FastSmiOrObjectElementsAccessor< 1004 : FastSmiOrObjectElementsAccessor<
1005 FastHoleySmiElementsAccessor, 1005 FastHoleySmiElementsAccessor,
1006 ElementsKindTraits<FAST_HOLEY_SMI_ELEMENTS> >(name) {} 1006 ElementsKindTraits<FAST_HOLEY_SMI_ELEMENTS> >(name) {}
1007 }; 1007 };
1008 1008
1009 1009
1010 class FastPackedObjectElementsAccessor 1010 class FastPackedObjectElementsAccessor
1011 : public FastSmiOrObjectElementsAccessor< 1011 : public FastSmiOrObjectElementsAccessor<
1012 FastPackedObjectElementsAccessor, 1012 FastPackedObjectElementsAccessor,
1013 ElementsKindTraits<FAST_ELEMENTS> > { 1013 ElementsKindTraits<FAST_ELEMENTS> > {
1014 public: 1014 public:
1015 explicit FastPackedObjectElementsAccessor(const char* name) 1015 explicit FastPackedObjectElementsAccessor(const char* name)
1016 : FastSmiOrObjectElementsAccessor< 1016 : FastSmiOrObjectElementsAccessor<
1017 FastPackedObjectElementsAccessor, 1017 FastPackedObjectElementsAccessor,
1018 ElementsKindTraits<FAST_ELEMENTS> >(name) {} 1018 ElementsKindTraits<FAST_ELEMENTS> >(name) {}
1019 }; 1019 };
1020 1020
1021 1021
1022 class FastHoleyObjectElementsAccessor 1022 class FastHoleyObjectElementsAccessor
1023 : public FastSmiOrObjectElementsAccessor< 1023 : public FastSmiOrObjectElementsAccessor<
1024 FastHoleyObjectElementsAccessor, 1024 FastHoleyObjectElementsAccessor,
1025 ElementsKindTraits<FAST_HOLEY_ELEMENTS> > { 1025 ElementsKindTraits<FAST_HOLEY_ELEMENTS> > {
1026 public: 1026 public:
1027 explicit FastHoleyObjectElementsAccessor(const char* name) 1027 explicit FastHoleyObjectElementsAccessor(const char* name)
1028 : FastSmiOrObjectElementsAccessor< 1028 : FastSmiOrObjectElementsAccessor<
1029 FastHoleyObjectElementsAccessor, 1029 FastHoleyObjectElementsAccessor,
1030 ElementsKindTraits<FAST_HOLEY_ELEMENTS> >(name) {} 1030 ElementsKindTraits<FAST_HOLEY_ELEMENTS> >(name) {}
1031 }; 1031 };
1032 1032
1033 1033
1034 template<typename FastElementsAccessorSubclass, 1034 template<typename FastElementsAccessorSubclass,
1035 typename KindTraits> 1035 typename KindTraits>
1036 class FastDoubleElementsAccessor 1036 class FastDoubleElementsAccessor
1037 : public FastElementsAccessor<FastElementsAccessorSubclass, 1037 : public FastElementsAccessor<FastElementsAccessorSubclass,
1038 KindTraits, 1038 KindTraits,
1039 kDoubleSize> { 1039 kDoubleSize> {
1040 public: 1040 public:
1041 explicit FastDoubleElementsAccessor(const char* name) 1041 explicit FastDoubleElementsAccessor(const char* name)
1042 : FastElementsAccessor<FastElementsAccessorSubclass, 1042 : FastElementsAccessor<FastElementsAccessorSubclass,
1043 KindTraits, 1043 KindTraits,
1044 kDoubleSize>(name) {} 1044 kDoubleSize>(name) {}
1045 1045
1046 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, 1046 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj,
1047 uint32_t capacity, 1047 uint32_t capacity,
1048 uint32_t length) { 1048 uint32_t length) {
1049 return obj->SetFastDoubleElementsCapacityAndLength(capacity, 1049 return obj->SetFastDoubleElementsCapacityAndLength(capacity,
1050 length); 1050 length);
1051 } 1051 }
1052 1052
1053 protected: 1053 protected:
1054 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, 1054 static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
1055 uint32_t from_start, 1055 uint32_t from_start,
1056 FixedArrayBase* to, 1056 FixedArrayBase* to,
1057 ElementsKind to_kind, 1057 ElementsKind to_kind,
1058 uint32_t to_start, 1058 uint32_t to_start,
1059 int packed_size, 1059 int packed_size,
1060 int copy_size) { 1060 int copy_size) {
1061 switch (to_kind) { 1061 switch (to_kind) {
1062 case FAST_SMI_ELEMENTS: 1062 case FAST_SMI_ELEMENTS:
1063 case FAST_ELEMENTS: 1063 case FAST_ELEMENTS:
1064 case FAST_HOLEY_SMI_ELEMENTS: 1064 case FAST_HOLEY_SMI_ELEMENTS:
1065 case FAST_HOLEY_ELEMENTS: 1065 case FAST_HOLEY_ELEMENTS:
1066 return CopyDoubleToObjectElements( 1066 return CopyDoubleToObjectElements(
1067 FixedDoubleArray::cast(from), from_start, FixedArray::cast(to), 1067 FixedDoubleArray::cast(from), from_start, FixedArray::cast(to),
1068 to_kind, to_start, copy_size); 1068 to_kind, to_start, copy_size);
1069 case FAST_DOUBLE_ELEMENTS: 1069 case FAST_DOUBLE_ELEMENTS:
1070 case FAST_HOLEY_DOUBLE_ELEMENTS: 1070 case FAST_HOLEY_DOUBLE_ELEMENTS:
1071 CopyDoubleToDoubleElements(FixedDoubleArray::cast(from), from_start, 1071 CopyDoubleToDoubleElements(FixedDoubleArray::cast(from), from_start,
1072 FixedDoubleArray::cast(to), 1072 FixedDoubleArray::cast(to),
1073 to_start, copy_size); 1073 to_start, copy_size);
1074 return from; 1074 return from;
1075 default: 1075 default:
1076 UNREACHABLE(); 1076 UNREACHABLE();
1077 } 1077 }
1078 return to->GetHeap()->undefined_value(); 1078 return to->GetHeap()->undefined_value();
1079 } 1079 }
1080 }; 1080 };
1081 1081
1082 1082
1083 class FastPackedDoubleElementsAccessor 1083 class FastPackedDoubleElementsAccessor
1084 : public FastDoubleElementsAccessor< 1084 : public FastDoubleElementsAccessor<
1085 FastPackedDoubleElementsAccessor, 1085 FastPackedDoubleElementsAccessor,
1086 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> > { 1086 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> > {
1087 public: 1087 public:
1088 friend class ElementsAccessorBase<FastPackedDoubleElementsAccessor, 1088 friend class ElementsAccessorBase<FastPackedDoubleElementsAccessor,
1089 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >; 1089 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >;
1090 explicit FastPackedDoubleElementsAccessor(const char* name) 1090 explicit FastPackedDoubleElementsAccessor(const char* name)
1091 : FastDoubleElementsAccessor< 1091 : FastDoubleElementsAccessor<
1092 FastPackedDoubleElementsAccessor, 1092 FastPackedDoubleElementsAccessor,
1093 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >(name) {} 1093 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >(name) {}
1094 }; 1094 };
1095 1095
1096 1096
1097 class FastHoleyDoubleElementsAccessor 1097 class FastHoleyDoubleElementsAccessor
1098 : public FastDoubleElementsAccessor< 1098 : public FastDoubleElementsAccessor<
1099 FastHoleyDoubleElementsAccessor, 1099 FastHoleyDoubleElementsAccessor,
1100 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > { 1100 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > {
1101 public: 1101 public:
1102 friend class ElementsAccessorBase< 1102 friend class ElementsAccessorBase<
1103 FastHoleyDoubleElementsAccessor, 1103 FastHoleyDoubleElementsAccessor,
1104 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >; 1104 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >;
1105 explicit FastHoleyDoubleElementsAccessor(const char* name) 1105 explicit FastHoleyDoubleElementsAccessor(const char* name)
1106 : FastDoubleElementsAccessor< 1106 : FastDoubleElementsAccessor<
1107 FastHoleyDoubleElementsAccessor, 1107 FastHoleyDoubleElementsAccessor,
1108 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {} 1108 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {}
1109 }; 1109 };
1110 1110
1111 1111
1112 // Super class for all external element arrays. 1112 // Super class for all external element arrays.
1113 template<typename ExternalElementsAccessorSubclass, 1113 template<typename ExternalElementsAccessorSubclass,
1114 ElementsKind Kind> 1114 ElementsKind Kind>
1115 class ExternalElementsAccessor 1115 class ExternalElementsAccessor
1116 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, 1116 : public ElementsAccessorBase<ExternalElementsAccessorSubclass,
1117 ElementsKindTraits<Kind> > { 1117 ElementsKindTraits<Kind> > {
1118 public: 1118 public:
1119 explicit ExternalElementsAccessor(const char* name) 1119 explicit ExternalElementsAccessor(const char* name)
1120 : ElementsAccessorBase<ExternalElementsAccessorSubclass, 1120 : ElementsAccessorBase<ExternalElementsAccessorSubclass,
1121 ElementsKindTraits<Kind> >(name) {} 1121 ElementsKindTraits<Kind> >(name) {}
1122 1122
1123 protected: 1123 protected:
1124 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; 1124 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore;
1125 1125
1126 friend class ElementsAccessorBase<ExternalElementsAccessorSubclass, 1126 friend class ElementsAccessorBase<ExternalElementsAccessorSubclass,
1127 ElementsKindTraits<Kind> >; 1127 ElementsKindTraits<Kind> >;
1128 1128
1129 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, 1129 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver,
1130 JSObject* obj, 1130 JSObject* obj,
1131 uint32_t key, 1131 uint32_t key,
1132 BackingStore* backing_store) { 1132 BackingStore* backing_store) {
1133 return 1133 return
1134 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store) 1134 key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store)
1135 ? backing_store->get(key) 1135 ? backing_store->get(key)
1136 : backing_store->GetHeap()->undefined_value(); 1136 : backing_store->GetHeap()->undefined_value();
1137 } 1137 }
1138 1138
1139 MUST_USE_RESULT static MaybeObject* SetLengthImpl( 1139 MUST_USE_RESULT static MaybeObject* SetLengthImpl(
1140 JSObject* obj, 1140 JSObject* obj,
1141 Object* length, 1141 Object* length,
1142 BackingStore* backing_store) { 1142 BackingStore* backing_store) {
1143 // External arrays do not support changing their length. 1143 // External arrays do not support changing their length.
1144 UNREACHABLE(); 1144 UNREACHABLE();
1145 return obj; 1145 return obj;
1146 } 1146 }
1147 1147
1148 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, 1148 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj,
1149 uint32_t key, 1149 uint32_t key,
1150 JSReceiver::DeleteMode mode) { 1150 JSReceiver::DeleteMode mode) {
1151 // External arrays always ignore deletes. 1151 // External arrays always ignore deletes.
1152 return obj->GetHeap()->true_value(); 1152 return obj->GetHeap()->true_value();
1153 } 1153 }
1154 1154
1155 static bool HasElementImpl(Object* receiver, 1155 static bool HasElementImpl(Object* receiver,
1156 JSObject* holder, 1156 JSObject* holder,
1157 uint32_t key, 1157 uint32_t key,
1158 BackingStore* backing_store) { 1158 BackingStore* backing_store) {
1159 uint32_t capacity = 1159 uint32_t capacity =
1160 ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store); 1160 ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store);
1161 return key < capacity; 1161 return key < capacity;
1162 } 1162 }
1163 }; 1163 };
1164 1164
1165 1165
1166 class ExternalByteElementsAccessor 1166 class ExternalByteElementsAccessor
1167 : public ExternalElementsAccessor<ExternalByteElementsAccessor, 1167 : public ExternalElementsAccessor<ExternalByteElementsAccessor,
1168 EXTERNAL_BYTE_ELEMENTS> { 1168 EXTERNAL_BYTE_ELEMENTS> {
1169 public: 1169 public:
1170 explicit ExternalByteElementsAccessor(const char* name) 1170 explicit ExternalByteElementsAccessor(const char* name)
1171 : ExternalElementsAccessor<ExternalByteElementsAccessor, 1171 : ExternalElementsAccessor<ExternalByteElementsAccessor,
1172 EXTERNAL_BYTE_ELEMENTS>(name) {} 1172 EXTERNAL_BYTE_ELEMENTS>(name) {}
1173 }; 1173 };
1174 1174
1175 1175
1176 class ExternalUnsignedByteElementsAccessor 1176 class ExternalUnsignedByteElementsAccessor
1177 : public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor, 1177 : public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
1178 EXTERNAL_UNSIGNED_BYTE_ELEMENTS> { 1178 EXTERNAL_UNSIGNED_BYTE_ELEMENTS> {
1179 public: 1179 public:
1180 explicit ExternalUnsignedByteElementsAccessor(const char* name) 1180 explicit ExternalUnsignedByteElementsAccessor(const char* name)
1181 : ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor, 1181 : ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
1182 EXTERNAL_UNSIGNED_BYTE_ELEMENTS>(name) {} 1182 EXTERNAL_UNSIGNED_BYTE_ELEMENTS>(name) {}
1183 }; 1183 };
1184 1184
1185 1185
1186 class ExternalShortElementsAccessor 1186 class ExternalShortElementsAccessor
1187 : public ExternalElementsAccessor<ExternalShortElementsAccessor, 1187 : public ExternalElementsAccessor<ExternalShortElementsAccessor,
1188 EXTERNAL_SHORT_ELEMENTS> { 1188 EXTERNAL_SHORT_ELEMENTS> {
1189 public: 1189 public:
1190 explicit ExternalShortElementsAccessor(const char* name) 1190 explicit ExternalShortElementsAccessor(const char* name)
1191 : ExternalElementsAccessor<ExternalShortElementsAccessor, 1191 : ExternalElementsAccessor<ExternalShortElementsAccessor,
1192 EXTERNAL_SHORT_ELEMENTS>(name) {} 1192 EXTERNAL_SHORT_ELEMENTS>(name) {}
1193 }; 1193 };
1194 1194
1195 1195
1196 class ExternalUnsignedShortElementsAccessor 1196 class ExternalUnsignedShortElementsAccessor
1197 : public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor, 1197 : public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
1198 EXTERNAL_UNSIGNED_SHORT_ELEMENTS> { 1198 EXTERNAL_UNSIGNED_SHORT_ELEMENTS> {
1199 public: 1199 public:
1200 explicit ExternalUnsignedShortElementsAccessor(const char* name) 1200 explicit ExternalUnsignedShortElementsAccessor(const char* name)
1201 : ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor, 1201 : ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
1202 EXTERNAL_UNSIGNED_SHORT_ELEMENTS>(name) {} 1202 EXTERNAL_UNSIGNED_SHORT_ELEMENTS>(name) {}
1203 }; 1203 };
1204 1204
1205 1205
1206 class ExternalIntElementsAccessor 1206 class ExternalIntElementsAccessor
1207 : public ExternalElementsAccessor<ExternalIntElementsAccessor, 1207 : public ExternalElementsAccessor<ExternalIntElementsAccessor,
1208 EXTERNAL_INT_ELEMENTS> { 1208 EXTERNAL_INT_ELEMENTS> {
1209 public: 1209 public:
1210 explicit ExternalIntElementsAccessor(const char* name) 1210 explicit ExternalIntElementsAccessor(const char* name)
1211 : ExternalElementsAccessor<ExternalIntElementsAccessor, 1211 : ExternalElementsAccessor<ExternalIntElementsAccessor,
1212 EXTERNAL_INT_ELEMENTS>(name) {} 1212 EXTERNAL_INT_ELEMENTS>(name) {}
1213 }; 1213 };
1214 1214
1215 1215
1216 class ExternalUnsignedIntElementsAccessor 1216 class ExternalUnsignedIntElementsAccessor
1217 : public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor, 1217 : public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
1218 EXTERNAL_UNSIGNED_INT_ELEMENTS> { 1218 EXTERNAL_UNSIGNED_INT_ELEMENTS> {
1219 public: 1219 public:
1220 explicit ExternalUnsignedIntElementsAccessor(const char* name) 1220 explicit ExternalUnsignedIntElementsAccessor(const char* name)
1221 : ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor, 1221 : ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
1222 EXTERNAL_UNSIGNED_INT_ELEMENTS>(name) {} 1222 EXTERNAL_UNSIGNED_INT_ELEMENTS>(name) {}
1223 }; 1223 };
1224 1224
1225 1225
1226 class ExternalFloatElementsAccessor 1226 class ExternalFloatElementsAccessor
1227 : public ExternalElementsAccessor<ExternalFloatElementsAccessor, 1227 : public ExternalElementsAccessor<ExternalFloatElementsAccessor,
1228 EXTERNAL_FLOAT_ELEMENTS> { 1228 EXTERNAL_FLOAT_ELEMENTS> {
1229 public: 1229 public:
1230 explicit ExternalFloatElementsAccessor(const char* name) 1230 explicit ExternalFloatElementsAccessor(const char* name)
1231 : ExternalElementsAccessor<ExternalFloatElementsAccessor, 1231 : ExternalElementsAccessor<ExternalFloatElementsAccessor,
1232 EXTERNAL_FLOAT_ELEMENTS>(name) {} 1232 EXTERNAL_FLOAT_ELEMENTS>(name) {}
1233 }; 1233 };
1234 1234
1235 1235
1236 class ExternalDoubleElementsAccessor 1236 class ExternalDoubleElementsAccessor
1237 : public ExternalElementsAccessor<ExternalDoubleElementsAccessor, 1237 : public ExternalElementsAccessor<ExternalDoubleElementsAccessor,
1238 EXTERNAL_DOUBLE_ELEMENTS> { 1238 EXTERNAL_DOUBLE_ELEMENTS> {
1239 public: 1239 public:
1240 explicit ExternalDoubleElementsAccessor(const char* name) 1240 explicit ExternalDoubleElementsAccessor(const char* name)
1241 : ExternalElementsAccessor<ExternalDoubleElementsAccessor, 1241 : ExternalElementsAccessor<ExternalDoubleElementsAccessor,
1242 EXTERNAL_DOUBLE_ELEMENTS>(name) {} 1242 EXTERNAL_DOUBLE_ELEMENTS>(name) {}
1243 }; 1243 };
1244 1244
1245 1245
1246 class PixelElementsAccessor 1246 class PixelElementsAccessor
1247 : public ExternalElementsAccessor<PixelElementsAccessor, 1247 : public ExternalElementsAccessor<PixelElementsAccessor,
1248 EXTERNAL_PIXEL_ELEMENTS> { 1248 EXTERNAL_PIXEL_ELEMENTS> {
1249 public: 1249 public:
1250 explicit PixelElementsAccessor(const char* name) 1250 explicit PixelElementsAccessor(const char* name)
1251 : ExternalElementsAccessor<PixelElementsAccessor, 1251 : ExternalElementsAccessor<PixelElementsAccessor,
1252 EXTERNAL_PIXEL_ELEMENTS>(name) {} 1252 EXTERNAL_PIXEL_ELEMENTS>(name) {}
1253 }; 1253 };
1254 1254
1255 1255
1256 class DictionaryElementsAccessor 1256 class DictionaryElementsAccessor
1257 : public ElementsAccessorBase<DictionaryElementsAccessor, 1257 : public ElementsAccessorBase<DictionaryElementsAccessor,
1258 ElementsKindTraits<DICTIONARY_ELEMENTS> > { 1258 ElementsKindTraits<DICTIONARY_ELEMENTS> > {
1259 public: 1259 public:
1260 explicit DictionaryElementsAccessor(const char* name) 1260 explicit DictionaryElementsAccessor(const char* name)
1261 : ElementsAccessorBase<DictionaryElementsAccessor, 1261 : ElementsAccessorBase<DictionaryElementsAccessor,
1262 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} 1262 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {}
1263 1263
1264 // Adjusts the length of the dictionary backing store and returns the new 1264 // Adjusts the length of the dictionary backing store and returns the new
1265 // length according to ES5 section 15.4.5.2 behavior. 1265 // length according to ES5 section 15.4.5.2 behavior.
1266 MUST_USE_RESULT static MaybeObject* SetLengthWithoutNormalize( 1266 MUST_USE_RESULT static MaybeObject* SetLengthWithoutNormalize(
1267 SeededNumberDictionary* dict, 1267 SeededNumberDictionary* dict,
1268 JSArray* array, 1268 JSArray* array,
1269 Object* length_object, 1269 Object* length_object,
1270 uint32_t length) { 1270 uint32_t length) {
1271 Heap* heap = array->GetHeap(); 1271 if (length == 0) {
1272 int capacity = dict->Capacity();
1273 uint32_t new_length = length;
1274 uint32_t old_length = static_cast<uint32_t>(array->length()->Number());
1275 if (new_length < old_length) {
1276 // Find last non-deletable element in range of elements to be
1277 // deleted and adjust range accordingly.
1278 for (int i = 0; i < capacity; i++) {
1279 Object* key = dict->KeyAt(i);
1280 if (key->IsNumber()) {
1281 uint32_t number = static_cast<uint32_t>(key->Number());
1282 if (new_length <= number && number < old_length) {
1283 PropertyDetails details = dict->DetailsAt(i);
1284 if (details.IsDontDelete()) new_length = number + 1;
1285 }
1286 }
1287 }
1288 if (new_length != length) {
1289 MaybeObject* maybe_object = heap->NumberFromUint32(new_length);
1290 if (!maybe_object->To(&length_object)) return maybe_object;
1291 }
1292 }
1293
1294 if (new_length == 0) {
1295 // If the length of a slow array is reset to zero, we clear 1272 // If the length of a slow array is reset to zero, we clear
1296 // the array and flush backing storage. This has the added 1273 // the array and flush backing storage. This has the added
1297 // benefit that the array returns to fast mode. 1274 // benefit that the array returns to fast mode.
1298 Object* obj; 1275 Object* obj;
1299 MaybeObject* maybe_obj = array->ResetElements(); 1276 MaybeObject* maybe_obj = array->ResetElements();
1300 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 1277 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1301 } else { 1278 } else {
1302 // Remove elements that should be deleted. 1279 uint32_t new_length = length;
1303 int removed_entries = 0; 1280 uint32_t old_length = static_cast<uint32_t>(array->length()->Number());
1304 Object* the_hole_value = heap->the_hole_value(); 1281 if (new_length < old_length) {
1305 for (int i = 0; i < capacity; i++) { 1282 // Find last non-deletable element in range of elements to be
1306 Object* key = dict->KeyAt(i); 1283 // deleted and adjust range accordingly.
1307 if (key->IsNumber()) { 1284 Heap* heap = array->GetHeap();
1308 uint32_t number = static_cast<uint32_t>(key->Number()); 1285 int capacity = dict->Capacity();
1309 if (new_length <= number && number < old_length) { 1286 for (int i = 0; i < capacity; i++) {
1310 dict->SetEntry(i, the_hole_value, the_hole_value); 1287 Object* key = dict->KeyAt(i);
1311 removed_entries++; 1288 if (key->IsNumber()) {
1289 uint32_t number = static_cast<uint32_t>(key->Number());
1290 if (new_length <= number && number < old_length) {
1291 PropertyDetails details = dict->DetailsAt(i);
1292 if (details.IsDontDelete()) new_length = number + 1;
1293 }
1312 } 1294 }
1313 } 1295 }
1314 } 1296 if (new_length != length) {
1297 MaybeObject* maybe_object = heap->NumberFromUint32(new_length);
1298 if (!maybe_object->To(&length_object)) return maybe_object;
1299 }
1315 1300
1316 // Update the number of elements. 1301 // Remove elements that should be deleted.
1317 dict->ElementsRemoved(removed_entries); 1302 int removed_entries = 0;
1303 Object* the_hole_value = heap->the_hole_value();
1304 for (int i = 0; i < capacity; i++) {
1305 Object* key = dict->KeyAt(i);
1306 if (key->IsNumber()) {
1307 uint32_t number = static_cast<uint32_t>(key->Number());
1308 if (new_length <= number && number < old_length) {
1309 dict->SetEntry(i, the_hole_value, the_hole_value);
1310 removed_entries++;
1311 }
1312 }
1313 }
1314
1315 // Update the number of elements.
1316 dict->ElementsRemoved(removed_entries);
1317 }
1318 } 1318 }
1319 return length_object; 1319 return length_object;
1320 } 1320 }
1321 1321
1322 MUST_USE_RESULT static MaybeObject* DeleteCommon( 1322 MUST_USE_RESULT static MaybeObject* DeleteCommon(
1323 JSObject* obj, 1323 JSObject* obj,
1324 uint32_t key, 1324 uint32_t key,
1325 JSReceiver::DeleteMode mode) { 1325 JSReceiver::DeleteMode mode) {
1326 Isolate* isolate = obj->GetIsolate(); 1326 Isolate* isolate = obj->GetIsolate();
1327 Heap* heap = isolate->heap(); 1327 Heap* heap = isolate->heap();
1328 FixedArray* backing_store = FixedArray::cast(obj->elements()); 1328 FixedArray* backing_store = FixedArray::cast(obj->elements());
1329 bool is_arguments = 1329 bool is_arguments =
1330 (obj->GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS); 1330 (obj->GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS);
1331 if (is_arguments) { 1331 if (is_arguments) {
1332 backing_store = FixedArray::cast(backing_store->get(1)); 1332 backing_store = FixedArray::cast(backing_store->get(1));
1333 } 1333 }
1334 SeededNumberDictionary* dictionary = 1334 SeededNumberDictionary* dictionary =
1335 SeededNumberDictionary::cast(backing_store); 1335 SeededNumberDictionary::cast(backing_store);
1336 int entry = dictionary->FindEntry(key); 1336 int entry = dictionary->FindEntry(key);
1337 if (entry != SeededNumberDictionary::kNotFound) { 1337 if (entry != SeededNumberDictionary::kNotFound) {
1338 Object* result = dictionary->DeleteProperty(entry, mode); 1338 Object* result = dictionary->DeleteProperty(entry, mode);
1339 if (result == heap->true_value()) { 1339 if (result == heap->true_value()) {
1340 MaybeObject* maybe_elements = dictionary->Shrink(key); 1340 MaybeObject* maybe_elements = dictionary->Shrink(key);
1341 FixedArray* new_elements = NULL; 1341 FixedArray* new_elements = NULL;
1342 if (!maybe_elements->To(&new_elements)) { 1342 if (!maybe_elements->To(&new_elements)) {
1343 return maybe_elements; 1343 return maybe_elements;
1344 } 1344 }
1345 if (is_arguments) { 1345 if (is_arguments) {
1346 FixedArray::cast(obj->elements())->set(1, new_elements); 1346 FixedArray::cast(obj->elements())->set(1, new_elements);
1347 } else { 1347 } else {
1348 obj->set_elements(new_elements); 1348 obj->set_elements(new_elements);
1349 } 1349 }
1350 } 1350 }
1351 if (mode == JSObject::STRICT_DELETION && 1351 if (mode == JSObject::STRICT_DELETION &&
1352 result == heap->false_value()) { 1352 result == heap->false_value()) {
1353 // In strict mode, attempting to delete a non-configurable property 1353 // In strict mode, attempting to delete a non-configurable property
1354 // throws an exception. 1354 // throws an exception.
1355 HandleScope scope(isolate); 1355 HandleScope scope(isolate);
1356 Handle<Object> holder(obj); 1356 Handle<Object> holder(obj);
1357 Handle<Object> name = isolate->factory()->NewNumberFromUint(key); 1357 Handle<Object> name = isolate->factory()->NewNumberFromUint(key);
1358 Handle<Object> args[2] = { name, holder }; 1358 Handle<Object> args[2] = { name, holder };
1359 Handle<Object> error = 1359 Handle<Object> error =
1360 isolate->factory()->NewTypeError("strict_delete_property", 1360 isolate->factory()->NewTypeError("strict_delete_property",
1361 HandleVector(args, 2)); 1361 HandleVector(args, 2));
1362 return isolate->Throw(*error); 1362 return isolate->Throw(*error);
1363 } 1363 }
1364 } 1364 }
1365 return heap->true_value(); 1365 return heap->true_value();
1366 } 1366 }
1367 1367
1368 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, 1368 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
1369 uint32_t from_start, 1369 uint32_t from_start,
1370 FixedArrayBase* to, 1370 FixedArrayBase* to,
1371 ElementsKind to_kind, 1371 ElementsKind to_kind,
1372 uint32_t to_start, 1372 uint32_t to_start,
1373 int packed_size, 1373 int packed_size,
1374 int copy_size) { 1374 int copy_size) {
1375 switch (to_kind) { 1375 switch (to_kind) {
1376 case FAST_SMI_ELEMENTS: 1376 case FAST_SMI_ELEMENTS:
1377 case FAST_ELEMENTS: 1377 case FAST_ELEMENTS:
1378 case FAST_HOLEY_SMI_ELEMENTS: 1378 case FAST_HOLEY_SMI_ELEMENTS:
1379 case FAST_HOLEY_ELEMENTS: 1379 case FAST_HOLEY_ELEMENTS:
1380 CopyDictionaryToObjectElements( 1380 CopyDictionaryToObjectElements(
1381 SeededNumberDictionary::cast(from), from_start, 1381 SeededNumberDictionary::cast(from), from_start,
1382 FixedArray::cast(to), to_kind, to_start, copy_size); 1382 FixedArray::cast(to), to_kind, to_start, copy_size);
1383 return from; 1383 return from;
1384 case FAST_DOUBLE_ELEMENTS: 1384 case FAST_DOUBLE_ELEMENTS:
1385 case FAST_HOLEY_DOUBLE_ELEMENTS: 1385 case FAST_HOLEY_DOUBLE_ELEMENTS:
1386 CopyDictionaryToDoubleElements( 1386 CopyDictionaryToDoubleElements(
1387 SeededNumberDictionary::cast(from), from_start, 1387 SeededNumberDictionary::cast(from), from_start,
1388 FixedDoubleArray::cast(to), to_start, copy_size); 1388 FixedDoubleArray::cast(to), to_start, copy_size);
1389 return from; 1389 return from;
1390 default: 1390 default:
1391 UNREACHABLE(); 1391 UNREACHABLE();
1392 } 1392 }
1393 return to->GetHeap()->undefined_value(); 1393 return to->GetHeap()->undefined_value();
1394 } 1394 }
1395 1395
1396 1396
1397 protected: 1397 protected:
1398 friend class ElementsAccessorBase<DictionaryElementsAccessor, 1398 friend class ElementsAccessorBase<DictionaryElementsAccessor,
1399 ElementsKindTraits<DICTIONARY_ELEMENTS> >; 1399 ElementsKindTraits<DICTIONARY_ELEMENTS> >;
1400 1400
1401 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, 1401 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj,
1402 uint32_t key, 1402 uint32_t key,
1403 JSReceiver::DeleteMode mode) { 1403 JSReceiver::DeleteMode mode) {
1404 return DeleteCommon(obj, key, mode); 1404 return DeleteCommon(obj, key, mode);
1405 } 1405 }
1406 1406
1407 MUST_USE_RESULT static MaybeObject* GetImpl( 1407 MUST_USE_RESULT static MaybeObject* GetImpl(
1408 Object* receiver, 1408 Object* receiver,
1409 JSObject* obj, 1409 JSObject* obj,
1410 uint32_t key, 1410 uint32_t key,
1411 SeededNumberDictionary* backing_store) { 1411 SeededNumberDictionary* backing_store) {
1412 int entry = backing_store->FindEntry(key); 1412 int entry = backing_store->FindEntry(key);
1413 if (entry != SeededNumberDictionary::kNotFound) { 1413 if (entry != SeededNumberDictionary::kNotFound) {
1414 Object* element = backing_store->ValueAt(entry); 1414 Object* element = backing_store->ValueAt(entry);
1415 PropertyDetails details = backing_store->DetailsAt(entry); 1415 PropertyDetails details = backing_store->DetailsAt(entry);
1416 if (details.type() == CALLBACKS) { 1416 if (details.type() == CALLBACKS) {
1417 return obj->GetElementWithCallback(receiver, 1417 return obj->GetElementWithCallback(receiver,
1418 element, 1418 element,
1419 key, 1419 key,
1420 obj); 1420 obj);
1421 } else { 1421 } else {
1422 return element; 1422 return element;
1423 } 1423 }
1424 } 1424 }
1425 return obj->GetHeap()->the_hole_value(); 1425 return obj->GetHeap()->the_hole_value();
1426 } 1426 }
1427 1427
1428 static bool HasElementImpl(Object* receiver, 1428 static bool HasElementImpl(Object* receiver,
1429 JSObject* holder, 1429 JSObject* holder,
1430 uint32_t key, 1430 uint32_t key,
1431 SeededNumberDictionary* backing_store) { 1431 SeededNumberDictionary* backing_store) {
1432 return backing_store->FindEntry(key) != 1432 return backing_store->FindEntry(key) !=
1433 SeededNumberDictionary::kNotFound; 1433 SeededNumberDictionary::kNotFound;
1434 } 1434 }
1435 1435
1436 static uint32_t GetKeyForIndexImpl(SeededNumberDictionary* dict, 1436 static uint32_t GetKeyForIndexImpl(SeededNumberDictionary* dict,
1437 uint32_t index) { 1437 uint32_t index) {
1438 Object* key = dict->KeyAt(index); 1438 Object* key = dict->KeyAt(index);
1439 return Smi::cast(key)->value(); 1439 return Smi::cast(key)->value();
1440 } 1440 }
1441 }; 1441 };
1442 1442
1443 1443
1444 class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase< 1444 class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase<
1445 NonStrictArgumentsElementsAccessor, 1445 NonStrictArgumentsElementsAccessor,
1446 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> > { 1446 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> > {
1447 public: 1447 public:
1448 explicit NonStrictArgumentsElementsAccessor(const char* name) 1448 explicit NonStrictArgumentsElementsAccessor(const char* name)
1449 : ElementsAccessorBase< 1449 : ElementsAccessorBase<
1450 NonStrictArgumentsElementsAccessor, 1450 NonStrictArgumentsElementsAccessor,
1451 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >(name) {} 1451 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >(name) {}
1452 protected: 1452 protected:
1453 friend class ElementsAccessorBase< 1453 friend class ElementsAccessorBase<
1454 NonStrictArgumentsElementsAccessor, 1454 NonStrictArgumentsElementsAccessor,
1455 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >; 1455 ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >;
1456 1456
1457 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver, 1457 MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver,
1458 JSObject* obj, 1458 JSObject* obj,
1459 uint32_t key, 1459 uint32_t key,
1460 FixedArray* parameter_map) { 1460 FixedArray* parameter_map) {
1461 Object* probe = GetParameterMapArg(obj, parameter_map, key); 1461 Object* probe = GetParameterMapArg(obj, parameter_map, key);
1462 if (!probe->IsTheHole()) { 1462 if (!probe->IsTheHole()) {
1463 Context* context = Context::cast(parameter_map->get(0)); 1463 Context* context = Context::cast(parameter_map->get(0));
1464 int context_index = Smi::cast(probe)->value(); 1464 int context_index = Smi::cast(probe)->value();
1465 ASSERT(!context->get(context_index)->IsTheHole()); 1465 ASSERT(!context->get(context_index)->IsTheHole());
1466 return context->get(context_index); 1466 return context->get(context_index);
1467 } else { 1467 } else {
1468 // Object is not mapped, defer to the arguments. 1468 // Object is not mapped, defer to the arguments.
1469 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); 1469 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
1470 MaybeObject* maybe_result = ElementsAccessor::ForArray(arguments)->Get( 1470 MaybeObject* maybe_result = ElementsAccessor::ForArray(arguments)->Get(
1471 receiver, obj, key, arguments); 1471 receiver, obj, key, arguments);
1472 Object* result; 1472 Object* result;
1473 if (!maybe_result->ToObject(&result)) return maybe_result; 1473 if (!maybe_result->ToObject(&result)) return maybe_result;
1474 // Elements of the arguments object in slow mode might be slow aliases. 1474 // Elements of the arguments object in slow mode might be slow aliases.
1475 if (result->IsAliasedArgumentsEntry()) { 1475 if (result->IsAliasedArgumentsEntry()) {
1476 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(result); 1476 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(result);
1477 Context* context = Context::cast(parameter_map->get(0)); 1477 Context* context = Context::cast(parameter_map->get(0));
1478 int context_index = entry->aliased_context_slot(); 1478 int context_index = entry->aliased_context_slot();
1479 ASSERT(!context->get(context_index)->IsTheHole()); 1479 ASSERT(!context->get(context_index)->IsTheHole());
1480 return context->get(context_index); 1480 return context->get(context_index);
1481 } else { 1481 } else {
1482 return result; 1482 return result;
1483 } 1483 }
1484 } 1484 }
1485 } 1485 }
1486 1486
1487 MUST_USE_RESULT static MaybeObject* SetLengthImpl( 1487 MUST_USE_RESULT static MaybeObject* SetLengthImpl(
1488 JSObject* obj, 1488 JSObject* obj,
1489 Object* length, 1489 Object* length,
1490 FixedArray* parameter_map) { 1490 FixedArray* parameter_map) {
1491 // TODO(mstarzinger): This was never implemented but will be used once we 1491 // TODO(mstarzinger): This was never implemented but will be used once we
1492 // correctly implement [[DefineOwnProperty]] on arrays. 1492 // correctly implement [[DefineOwnProperty]] on arrays.
1493 UNIMPLEMENTED(); 1493 UNIMPLEMENTED();
1494 return obj; 1494 return obj;
1495 } 1495 }
1496 1496
1497 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, 1497 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj,
1498 uint32_t key, 1498 uint32_t key,
1499 JSReceiver::DeleteMode mode) { 1499 JSReceiver::DeleteMode mode) {
1500 FixedArray* parameter_map = FixedArray::cast(obj->elements()); 1500 FixedArray* parameter_map = FixedArray::cast(obj->elements());
1501 Object* probe = GetParameterMapArg(obj, parameter_map, key); 1501 Object* probe = GetParameterMapArg(obj, parameter_map, key);
1502 if (!probe->IsTheHole()) { 1502 if (!probe->IsTheHole()) {
1503 // TODO(kmillikin): We could check if this was the last aliased 1503 // TODO(kmillikin): We could check if this was the last aliased
1504 // parameter, and revert to normal elements in that case. That 1504 // parameter, and revert to normal elements in that case. That
1505 // would enable GC of the context. 1505 // would enable GC of the context.
1506 parameter_map->set_the_hole(key + 2); 1506 parameter_map->set_the_hole(key + 2);
1507 } else { 1507 } else {
1508 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); 1508 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
1509 if (arguments->IsDictionary()) { 1509 if (arguments->IsDictionary()) {
1510 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode); 1510 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode);
1511 } else { 1511 } else {
1512 // It's difficult to access the version of DeleteCommon that is declared 1512 // It's difficult to access the version of DeleteCommon that is declared
1513 // in the templatized super class, call the concrete implementation in 1513 // in the templatized super class, call the concrete implementation in
1514 // the class for the most generalized ElementsKind subclass. 1514 // the class for the most generalized ElementsKind subclass.
1515 return FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, mode); 1515 return FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, mode);
1516 } 1516 }
1517 } 1517 }
1518 return obj->GetHeap()->true_value(); 1518 return obj->GetHeap()->true_value();
1519 } 1519 }
1520 1520
1521 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, 1521 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
1522 uint32_t from_start, 1522 uint32_t from_start,
1523 FixedArrayBase* to, 1523 FixedArrayBase* to,
1524 ElementsKind to_kind, 1524 ElementsKind to_kind,
1525 uint32_t to_start, 1525 uint32_t to_start,
1526 int packed_size, 1526 int packed_size,
1527 int copy_size) { 1527 int copy_size) {
1528 FixedArray* parameter_map = FixedArray::cast(from); 1528 FixedArray* parameter_map = FixedArray::cast(from);
1529 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); 1529 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
1530 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); 1530 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments);
1531 return accessor->CopyElements(NULL, from_start, to, to_kind, 1531 return accessor->CopyElements(NULL, from_start, to, to_kind,
1532 to_start, copy_size, arguments); 1532 to_start, copy_size, arguments);
1533 } 1533 }
1534 1534
1535 static uint32_t GetCapacityImpl(FixedArray* parameter_map) { 1535 static uint32_t GetCapacityImpl(FixedArray* parameter_map) {
1536 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); 1536 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
1537 return Max(static_cast<uint32_t>(parameter_map->length() - 2), 1537 return Max(static_cast<uint32_t>(parameter_map->length() - 2),
1538 ForArray(arguments)->GetCapacity(arguments)); 1538 ForArray(arguments)->GetCapacity(arguments));
1539 } 1539 }
1540 1540
1541 static uint32_t GetKeyForIndexImpl(FixedArray* dict, 1541 static uint32_t GetKeyForIndexImpl(FixedArray* dict,
1542 uint32_t index) { 1542 uint32_t index) {
1543 return index; 1543 return index;
1544 } 1544 }
1545 1545
1546 static bool HasElementImpl(Object* receiver, 1546 static bool HasElementImpl(Object* receiver,
1547 JSObject* holder, 1547 JSObject* holder,
1548 uint32_t key, 1548 uint32_t key,
1549 FixedArray* parameter_map) { 1549 FixedArray* parameter_map) {
1550 Object* probe = GetParameterMapArg(holder, parameter_map, key); 1550 Object* probe = GetParameterMapArg(holder, parameter_map, key);
1551 if (!probe->IsTheHole()) { 1551 if (!probe->IsTheHole()) {
1552 return true; 1552 return true;
1553 } else { 1553 } else {
1554 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); 1554 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
1555 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments); 1555 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments);
1556 return !accessor->Get(receiver, holder, key, arguments)->IsTheHole(); 1556 return !accessor->Get(receiver, holder, key, arguments)->IsTheHole();
1557 } 1557 }
1558 } 1558 }
1559 1559
1560 private: 1560 private:
1561 static Object* GetParameterMapArg(JSObject* holder, 1561 static Object* GetParameterMapArg(JSObject* holder,
1562 FixedArray* parameter_map, 1562 FixedArray* parameter_map,
1563 uint32_t key) { 1563 uint32_t key) {
1564 uint32_t length = holder->IsJSArray() 1564 uint32_t length = holder->IsJSArray()
1565 ? Smi::cast(JSArray::cast(holder)->length())->value() 1565 ? Smi::cast(JSArray::cast(holder)->length())->value()
1566 : parameter_map->length(); 1566 : parameter_map->length();
1567 return key < (length - 2 ) 1567 return key < (length - 2 )
1568 ? parameter_map->get(key + 2) 1568 ? parameter_map->get(key + 2)
1569 : parameter_map->GetHeap()->the_hole_value(); 1569 : parameter_map->GetHeap()->the_hole_value();
1570 } 1570 }
1571 }; 1571 };
1572 1572
1573 1573
1574 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { 1574 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) {
1575 switch (array->map()->instance_type()) { 1575 switch (array->map()->instance_type()) {
1576 case FIXED_ARRAY_TYPE: 1576 case FIXED_ARRAY_TYPE:
1577 if (array->IsDictionary()) { 1577 if (array->IsDictionary()) {
1578 return elements_accessors_[DICTIONARY_ELEMENTS]; 1578 return elements_accessors_[DICTIONARY_ELEMENTS];
1579 } else { 1579 } else {
1580 return elements_accessors_[FAST_HOLEY_ELEMENTS]; 1580 return elements_accessors_[FAST_HOLEY_ELEMENTS];
1581 } 1581 }
1582 case EXTERNAL_BYTE_ARRAY_TYPE: 1582 case EXTERNAL_BYTE_ARRAY_TYPE:
1583 return elements_accessors_[EXTERNAL_BYTE_ELEMENTS]; 1583 return elements_accessors_[EXTERNAL_BYTE_ELEMENTS];
1584 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: 1584 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
1585 return elements_accessors_[EXTERNAL_UNSIGNED_BYTE_ELEMENTS]; 1585 return elements_accessors_[EXTERNAL_UNSIGNED_BYTE_ELEMENTS];
1586 case EXTERNAL_SHORT_ARRAY_TYPE: 1586 case EXTERNAL_SHORT_ARRAY_TYPE:
1587 return elements_accessors_[EXTERNAL_SHORT_ELEMENTS]; 1587 return elements_accessors_[EXTERNAL_SHORT_ELEMENTS];
1588 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: 1588 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
1589 return elements_accessors_[EXTERNAL_UNSIGNED_SHORT_ELEMENTS]; 1589 return elements_accessors_[EXTERNAL_UNSIGNED_SHORT_ELEMENTS];
1590 case EXTERNAL_INT_ARRAY_TYPE: 1590 case EXTERNAL_INT_ARRAY_TYPE:
1591 return elements_accessors_[EXTERNAL_INT_ELEMENTS]; 1591 return elements_accessors_[EXTERNAL_INT_ELEMENTS];
1592 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: 1592 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
1593 return elements_accessors_[EXTERNAL_UNSIGNED_INT_ELEMENTS]; 1593 return elements_accessors_[EXTERNAL_UNSIGNED_INT_ELEMENTS];
1594 case EXTERNAL_FLOAT_ARRAY_TYPE: 1594 case EXTERNAL_FLOAT_ARRAY_TYPE:
1595 return elements_accessors_[EXTERNAL_FLOAT_ELEMENTS]; 1595 return elements_accessors_[EXTERNAL_FLOAT_ELEMENTS];
1596 case EXTERNAL_DOUBLE_ARRAY_TYPE: 1596 case EXTERNAL_DOUBLE_ARRAY_TYPE:
1597 return elements_accessors_[EXTERNAL_DOUBLE_ELEMENTS]; 1597 return elements_accessors_[EXTERNAL_DOUBLE_ELEMENTS];
1598 case EXTERNAL_PIXEL_ARRAY_TYPE: 1598 case EXTERNAL_PIXEL_ARRAY_TYPE:
1599 return elements_accessors_[EXTERNAL_PIXEL_ELEMENTS]; 1599 return elements_accessors_[EXTERNAL_PIXEL_ELEMENTS];
1600 default: 1600 default:
1601 UNREACHABLE(); 1601 UNREACHABLE();
1602 return NULL; 1602 return NULL;
1603 } 1603 }
1604 } 1604 }
1605 1605
1606 1606
1607 void ElementsAccessor::InitializeOncePerProcess() { 1607 void ElementsAccessor::InitializeOncePerProcess() {
1608 static ElementsAccessor* accessor_array[] = { 1608 static ElementsAccessor* accessor_array[] = {
1609 #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind), 1609 #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind),
1610 ELEMENTS_LIST(ACCESSOR_ARRAY) 1610 ELEMENTS_LIST(ACCESSOR_ARRAY)
1611 #undef ACCESSOR_ARRAY 1611 #undef ACCESSOR_ARRAY
1612 }; 1612 };
1613 1613
1614 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == 1614 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) ==
1615 kElementsKindCount); 1615 kElementsKindCount);
1616 1616
1617 elements_accessors_ = accessor_array; 1617 elements_accessors_ = accessor_array;
1618 } 1618 }
1619 1619
1620 1620
1621 void ElementsAccessor::TearDown() { 1621 void ElementsAccessor::TearDown() {
1622 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; 1622 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind];
1623 ELEMENTS_LIST(ACCESSOR_DELETE) 1623 ELEMENTS_LIST(ACCESSOR_DELETE)
1624 #undef ACCESSOR_DELETE 1624 #undef ACCESSOR_DELETE
1625 elements_accessors_ = NULL; 1625 elements_accessors_ = NULL;
1626 } 1626 }
1627 1627
1628 1628
1629 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> 1629 template <typename ElementsAccessorSubclass, typename ElementsKindTraits>
1630 MUST_USE_RESULT MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, 1630 MUST_USE_RESULT MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass,
1631 ElementsKindTraits>:: 1631 ElementsKindTraits>::
1632 SetLengthImpl(JSObject* obj, 1632 SetLengthImpl(JSObject* obj,
1633 Object* length, 1633 Object* length,
1634 typename ElementsKindTraits::BackingStore* backing_store) { 1634 typename ElementsKindTraits::BackingStore* backing_store) {
1635 JSArray* array = JSArray::cast(obj); 1635 JSArray* array = JSArray::cast(obj);
1636 1636
1637 // Fast case: The new length fits into a Smi. 1637 // Fast case: The new length fits into a Smi.
1638 MaybeObject* maybe_smi_length = length->ToSmi(); 1638 MaybeObject* maybe_smi_length = length->ToSmi();
1639 Object* smi_length = Smi::FromInt(0); 1639 Object* smi_length = Smi::FromInt(0);
1640 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { 1640 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) {
1641 const int value = Smi::cast(smi_length)->value(); 1641 const int value = Smi::cast(smi_length)->value();
1642 if (value >= 0) { 1642 if (value >= 0) {
1643 Object* new_length; 1643 Object* new_length;
1644 MaybeObject* result = ElementsAccessorSubclass:: 1644 MaybeObject* result = ElementsAccessorSubclass::
1645 SetLengthWithoutNormalize(backing_store, array, smi_length, value); 1645 SetLengthWithoutNormalize(backing_store, array, smi_length, value);
1646 if (!result->ToObject(&new_length)) return result; 1646 if (!result->ToObject(&new_length)) return result;
1647 ASSERT(new_length->IsSmi() || new_length->IsUndefined()); 1647 ASSERT(new_length->IsSmi() || new_length->IsUndefined());
1648 if (new_length->IsSmi()) { 1648 if (new_length->IsSmi()) {
1649 array->set_length(Smi::cast(new_length)); 1649 array->set_length(Smi::cast(new_length));
1650 return array; 1650 return array;
1651 } 1651 }
1652 } else { 1652 } else {
1653 return ThrowArrayLengthRangeError(array->GetHeap()); 1653 return ThrowArrayLengthRangeError(array->GetHeap());
1654 } 1654 }
1655 } 1655 }
1656 1656
1657 // Slow case: The new length does not fit into a Smi or conversion 1657 // Slow case: The new length does not fit into a Smi or conversion
1658 // to slow elements is needed for other reasons. 1658 // to slow elements is needed for other reasons.
1659 if (length->IsNumber()) { 1659 if (length->IsNumber()) {
1660 uint32_t value; 1660 uint32_t value;
1661 if (length->ToArrayIndex(&value)) { 1661 if (length->ToArrayIndex(&value)) {
1662 SeededNumberDictionary* dictionary; 1662 SeededNumberDictionary* dictionary;
1663 MaybeObject* maybe_object = array->NormalizeElements(); 1663 MaybeObject* maybe_object = array->NormalizeElements();
1664 if (!maybe_object->To(&dictionary)) return maybe_object; 1664 if (!maybe_object->To(&dictionary)) return maybe_object;
1665 Object* new_length; 1665 Object* new_length;
1666 MaybeObject* result = DictionaryElementsAccessor:: 1666 MaybeObject* result = DictionaryElementsAccessor::
1667 SetLengthWithoutNormalize(dictionary, array, length, value); 1667 SetLengthWithoutNormalize(dictionary, array, length, value);
1668 if (!result->ToObject(&new_length)) return result; 1668 if (!result->ToObject(&new_length)) return result;
1669 ASSERT(new_length->IsNumber()); 1669 ASSERT(new_length->IsNumber());
1670 array->set_length(new_length); 1670 array->set_length(new_length);
1671 return array; 1671 return array;
1672 } else { 1672 } else {
1673 return ThrowArrayLengthRangeError(array->GetHeap()); 1673 return ThrowArrayLengthRangeError(array->GetHeap());
1674 } 1674 }
1675 } 1675 }
1676 1676
1677 // Fall-back case: The new length is not a number so make the array 1677 // Fall-back case: The new length is not a number so make the array
1678 // size one and set only element to length. 1678 // size one and set only element to length.
1679 FixedArray* new_backing_store; 1679 FixedArray* new_backing_store;
1680 MaybeObject* maybe_obj = array->GetHeap()->AllocateFixedArray(1); 1680 MaybeObject* maybe_obj = array->GetHeap()->AllocateFixedArray(1);
1681 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; 1681 if (!maybe_obj->To(&new_backing_store)) return maybe_obj;
1682 new_backing_store->set(0, length); 1682 new_backing_store->set(0, length);
1683 { MaybeObject* result = array->SetContent(new_backing_store); 1683 { MaybeObject* result = array->SetContent(new_backing_store);
1684 if (result->IsFailure()) return result; 1684 if (result->IsFailure()) return result;
1685 } 1685 }
1686 return array; 1686 return array;
1687 } 1687 }
1688 1688
1689 1689
1690 } } // namespace v8::internal 1690 } } // namespace v8::internal
Powered by Google Project Hosting