OLD | NEW |
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 |
(...skipping 21 matching lines...) Expand all Loading... |
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 // - FastObjectElementsAccessor |
43 // - FastPackedSmiElementsAccessor | |
44 // - FastHoleySmiElementsAccessor | |
45 // - FastPackedObjectElementsAccessor | |
46 // - FastHoleyObjectElementsAccessor | |
47 // - FastDoubleElementsAccessor | 43 // - FastDoubleElementsAccessor |
48 // - FastPackedDoubleElementsAccessor | |
49 // - FastHoleyDoubleElementsAccessor | |
50 // - ExternalElementsAccessor (abstract) | 44 // - ExternalElementsAccessor (abstract) |
51 // - ExternalByteElementsAccessor | 45 // - ExternalByteElementsAccessor |
52 // - ExternalUnsignedByteElementsAccessor | 46 // - ExternalUnsignedByteElementsAccessor |
53 // - ExternalShortElementsAccessor | 47 // - ExternalShortElementsAccessor |
54 // - ExternalUnsignedShortElementsAccessor | 48 // - ExternalUnsignedShortElementsAccessor |
55 // - ExternalIntElementsAccessor | 49 // - ExternalIntElementsAccessor |
56 // - ExternalUnsignedIntElementsAccessor | 50 // - ExternalUnsignedIntElementsAccessor |
57 // - ExternalFloatElementsAccessor | 51 // - ExternalFloatElementsAccessor |
58 // - ExternalDoubleElementsAccessor | 52 // - ExternalDoubleElementsAccessor |
59 // - PixelElementsAccessor | 53 // - PixelElementsAccessor |
60 // - DictionaryElementsAccessor | 54 // - DictionaryElementsAccessor |
61 // - NonStrictArgumentsElementsAccessor | 55 // - NonStrictArgumentsElementsAccessor |
62 | 56 |
63 | 57 |
64 namespace v8 { | 58 namespace v8 { |
65 namespace internal { | 59 namespace internal { |
66 | 60 |
67 | 61 |
68 // First argument in list is the accessor class, the second argument is the | 62 // First argument in list is the accessor class, the second argument is the |
69 // accessor ElementsKind, and the third is the backing store class. Use the | 63 // accessor ElementsKind, and the third is the backing store class. Use the |
70 // fast element handler for smi-only arrays. The implementation is currently | 64 // fast element handler for smi-only arrays. The implementation is currently |
71 // identical. Note that the order must match that of the ElementsKind enum for | 65 // identical. Note that the order must match that of the ElementsKind enum for |
72 // the |accessor_array[]| below to work. | 66 // the |accessor_array[]| below to work. |
73 #define ELEMENTS_LIST(V) \ | 67 #define ELEMENTS_LIST(V) \ |
74 V(FastPackedSmiElementsAccessor, FAST_SMI_ELEMENTS, FixedArray) \ | 68 V(FastObjectElementsAccessor, FAST_SMI_ONLY_ELEMENTS, FixedArray) \ |
75 V(FastHoleySmiElementsAccessor, FAST_HOLEY_SMI_ELEMENTS, \ | 69 V(FastObjectElementsAccessor, FAST_ELEMENTS, FixedArray) \ |
76 FixedArray) \ | 70 V(FastDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, FixedDoubleArray) \ |
77 V(FastPackedObjectElementsAccessor, FAST_ELEMENTS, FixedArray) \ | |
78 V(FastHoleyObjectElementsAccessor, FAST_HOLEY_ELEMENTS, FixedArray) \ | |
79 V(FastPackedDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, \ | |
80 FixedDoubleArray) \ | |
81 V(FastHoleyDoubleElementsAccessor, FAST_HOLEY_DOUBLE_ELEMENTS, \ | |
82 FixedDoubleArray) \ | |
83 V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, \ | 71 V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, \ |
84 SeededNumberDictionary) \ | 72 SeededNumberDictionary) \ |
85 V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS, \ | 73 V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS, \ |
86 FixedArray) \ | 74 FixedArray) \ |
87 V(ExternalByteElementsAccessor, EXTERNAL_BYTE_ELEMENTS, \ | 75 V(ExternalByteElementsAccessor, EXTERNAL_BYTE_ELEMENTS, \ |
88 ExternalByteArray) \ | 76 ExternalByteArray) \ |
89 V(ExternalUnsignedByteElementsAccessor, \ | 77 V(ExternalUnsignedByteElementsAccessor, \ |
90 EXTERNAL_UNSIGNED_BYTE_ELEMENTS, ExternalUnsignedByteArray) \ | 78 EXTERNAL_UNSIGNED_BYTE_ELEMENTS, ExternalUnsignedByteArray) \ |
91 V(ExternalShortElementsAccessor, EXTERNAL_SHORT_ELEMENTS, \ | 79 V(ExternalShortElementsAccessor, EXTERNAL_SHORT_ELEMENTS, \ |
92 ExternalShortArray) \ | 80 ExternalShortArray) \ |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 | 132 |
145 | 133 |
146 void CopyObjectToObjectElements(FixedArray* from, | 134 void CopyObjectToObjectElements(FixedArray* from, |
147 ElementsKind from_kind, | 135 ElementsKind from_kind, |
148 uint32_t from_start, | 136 uint32_t from_start, |
149 FixedArray* to, | 137 FixedArray* to, |
150 ElementsKind to_kind, | 138 ElementsKind to_kind, |
151 uint32_t to_start, | 139 uint32_t to_start, |
152 int raw_copy_size) { | 140 int raw_copy_size) { |
153 ASSERT(to->map() != HEAP->fixed_cow_array_map()); | 141 ASSERT(to->map() != HEAP->fixed_cow_array_map()); |
| 142 ASSERT(from_kind == FAST_ELEMENTS || from_kind == FAST_SMI_ONLY_ELEMENTS); |
| 143 ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS); |
154 int copy_size = raw_copy_size; | 144 int copy_size = raw_copy_size; |
155 if (raw_copy_size < 0) { | 145 if (raw_copy_size < 0) { |
156 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 146 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
157 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 147 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
158 copy_size = Min(from->length() - from_start, | 148 copy_size = Min(from->length() - from_start, |
159 to->length() - to_start); | 149 to->length() - to_start); |
160 #ifdef DEBUG | 150 #ifdef DEBUG |
161 // FAST_*_ELEMENTS arrays cannot be uninitialized. Ensure they are already | 151 // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already |
162 // marked with the hole. | 152 // marked with the hole. |
163 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 153 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
164 for (int i = to_start + copy_size; i < to->length(); ++i) { | 154 for (int i = to_start + copy_size; i < to->length(); ++i) { |
165 ASSERT(to->get(i)->IsTheHole()); | 155 ASSERT(to->get(i)->IsTheHole()); |
166 } | 156 } |
167 } | 157 } |
168 #endif | 158 #endif |
169 } | 159 } |
170 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 160 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && |
171 (copy_size + static_cast<int>(from_start)) <= from->length()); | 161 (copy_size + static_cast<int>(from_start)) <= from->length()); |
172 if (copy_size == 0) return; | 162 if (copy_size == 0) return; |
173 ASSERT(IsFastSmiOrObjectElementsKind(from_kind)); | |
174 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); | |
175 Address to_address = to->address() + FixedArray::kHeaderSize; | 163 Address to_address = to->address() + FixedArray::kHeaderSize; |
176 Address from_address = from->address() + FixedArray::kHeaderSize; | 164 Address from_address = from->address() + FixedArray::kHeaderSize; |
177 CopyWords(reinterpret_cast<Object**>(to_address) + to_start, | 165 CopyWords(reinterpret_cast<Object**>(to_address) + to_start, |
178 reinterpret_cast<Object**>(from_address) + from_start, | 166 reinterpret_cast<Object**>(from_address) + from_start, |
179 copy_size); | 167 copy_size); |
180 if (IsFastObjectElementsKind(from_kind) && | 168 if (from_kind == FAST_ELEMENTS && to_kind == FAST_ELEMENTS) { |
181 IsFastObjectElementsKind(to_kind)) { | |
182 Heap* heap = from->GetHeap(); | 169 Heap* heap = from->GetHeap(); |
183 if (!heap->InNewSpace(to)) { | 170 if (!heap->InNewSpace(to)) { |
184 heap->RecordWrites(to->address(), | 171 heap->RecordWrites(to->address(), |
185 to->OffsetOfElementAt(to_start), | 172 to->OffsetOfElementAt(to_start), |
186 copy_size); | 173 copy_size); |
187 } | 174 } |
188 heap->incremental_marking()->RecordWrites(to); | 175 heap->incremental_marking()->RecordWrites(to); |
189 } | 176 } |
190 } | 177 } |
191 | 178 |
192 | 179 |
193 static void CopyDictionaryToObjectElements(SeededNumberDictionary* from, | 180 static void CopyDictionaryToObjectElements(SeededNumberDictionary* from, |
194 uint32_t from_start, | 181 uint32_t from_start, |
195 FixedArray* to, | 182 FixedArray* to, |
196 ElementsKind to_kind, | 183 ElementsKind to_kind, |
197 uint32_t to_start, | 184 uint32_t to_start, |
198 int raw_copy_size) { | 185 int raw_copy_size) { |
199 int copy_size = raw_copy_size; | 186 int copy_size = raw_copy_size; |
200 Heap* heap = from->GetHeap(); | 187 Heap* heap = from->GetHeap(); |
201 if (raw_copy_size < 0) { | 188 if (raw_copy_size < 0) { |
202 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 189 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
203 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 190 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
204 copy_size = from->max_number_key() + 1 - from_start; | 191 copy_size = from->max_number_key() + 1 - from_start; |
205 #ifdef DEBUG | 192 #ifdef DEBUG |
206 // Fast object arrays cannot be uninitialized. Ensure they are already | 193 // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already |
207 // marked with the hole. | 194 // marked with the hole. |
208 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 195 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
209 for (int i = to_start + copy_size; i < to->length(); ++i) { | 196 for (int i = to_start + copy_size; i < to->length(); ++i) { |
210 ASSERT(to->get(i)->IsTheHole()); | 197 ASSERT(to->get(i)->IsTheHole()); |
211 } | 198 } |
212 } | 199 } |
213 #endif | 200 #endif |
214 } | 201 } |
215 ASSERT(to != from); | 202 ASSERT(to != from); |
216 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); | 203 ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS); |
217 if (copy_size == 0) return; | 204 if (copy_size == 0) return; |
218 uint32_t to_length = to->length(); | 205 uint32_t to_length = to->length(); |
219 if (to_start + copy_size > to_length) { | 206 if (to_start + copy_size > to_length) { |
220 copy_size = to_length - to_start; | 207 copy_size = to_length - to_start; |
221 } | 208 } |
222 for (int i = 0; i < copy_size; i++) { | 209 for (int i = 0; i < copy_size; i++) { |
223 int entry = from->FindEntry(i + from_start); | 210 int entry = from->FindEntry(i + from_start); |
224 if (entry != SeededNumberDictionary::kNotFound) { | 211 if (entry != SeededNumberDictionary::kNotFound) { |
225 Object* value = from->ValueAt(entry); | 212 Object* value = from->ValueAt(entry); |
226 ASSERT(!value->IsTheHole()); | 213 ASSERT(!value->IsTheHole()); |
227 to->set(i + to_start, value, SKIP_WRITE_BARRIER); | 214 to->set(i + to_start, value, SKIP_WRITE_BARRIER); |
228 } else { | 215 } else { |
229 to->set_the_hole(i + to_start); | 216 to->set_the_hole(i + to_start); |
230 } | 217 } |
231 } | 218 } |
232 if (IsFastObjectElementsKind(to_kind)) { | 219 if (to_kind == FAST_ELEMENTS) { |
233 if (!heap->InNewSpace(to)) { | 220 if (!heap->InNewSpace(to)) { |
234 heap->RecordWrites(to->address(), | 221 heap->RecordWrites(to->address(), |
235 to->OffsetOfElementAt(to_start), | 222 to->OffsetOfElementAt(to_start), |
236 copy_size); | 223 copy_size); |
237 } | 224 } |
238 heap->incremental_marking()->RecordWrites(to); | 225 heap->incremental_marking()->RecordWrites(to); |
239 } | 226 } |
240 } | 227 } |
241 | 228 |
242 | 229 |
243 MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements( | 230 MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements( |
244 FixedDoubleArray* from, | 231 FixedDoubleArray* from, |
245 uint32_t from_start, | 232 uint32_t from_start, |
246 FixedArray* to, | 233 FixedArray* to, |
247 ElementsKind to_kind, | 234 ElementsKind to_kind, |
248 uint32_t to_start, | 235 uint32_t to_start, |
249 int raw_copy_size) { | 236 int raw_copy_size) { |
250 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); | 237 ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS); |
251 int copy_size = raw_copy_size; | 238 int copy_size = raw_copy_size; |
252 if (raw_copy_size < 0) { | 239 if (raw_copy_size < 0) { |
253 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 240 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
254 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 241 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
255 copy_size = Min(from->length() - from_start, | 242 copy_size = Min(from->length() - from_start, |
256 to->length() - to_start); | 243 to->length() - to_start); |
257 #ifdef DEBUG | 244 #ifdef DEBUG |
258 // FAST_*_ELEMENTS arrays cannot be uninitialized. Ensure they are already | 245 // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already |
259 // marked with the hole. | 246 // marked with the hole. |
260 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 247 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
261 for (int i = to_start + copy_size; i < to->length(); ++i) { | 248 for (int i = to_start + copy_size; i < to->length(); ++i) { |
262 ASSERT(to->get(i)->IsTheHole()); | 249 ASSERT(to->get(i)->IsTheHole()); |
263 } | 250 } |
264 } | 251 } |
265 #endif | 252 #endif |
266 } | 253 } |
267 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 254 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && |
268 (copy_size + static_cast<int>(from_start)) <= from->length()); | 255 (copy_size + static_cast<int>(from_start)) <= from->length()); |
269 if (copy_size == 0) return from; | 256 if (copy_size == 0) return from; |
270 for (int i = 0; i < copy_size; ++i) { | 257 for (int i = 0; i < copy_size; ++i) { |
271 if (IsFastSmiElementsKind(to_kind)) { | 258 if (to_kind == FAST_SMI_ONLY_ELEMENTS) { |
272 UNIMPLEMENTED(); | 259 UNIMPLEMENTED(); |
273 return Failure::Exception(); | 260 return Failure::Exception(); |
274 } else { | 261 } else { |
275 MaybeObject* maybe_value = from->get(i + from_start); | 262 MaybeObject* maybe_value = from->get(i + from_start); |
276 Object* value; | 263 Object* value; |
277 ASSERT(IsFastObjectElementsKind(to_kind)); | 264 ASSERT(to_kind == FAST_ELEMENTS); |
278 // Because Double -> Object elements transitions allocate HeapObjects | 265 // Because FAST_DOUBLE_ELEMENTS -> FAST_ELEMENT allocate HeapObjects |
279 // iteratively, the allocate must succeed within a single GC cycle, | 266 // iteratively, the allocate must succeed within a single GC cycle, |
280 // otherwise the retry after the GC will also fail. In order to ensure | 267 // otherwise the retry after the GC will also fail. In order to ensure |
281 // that no GC is triggered, allocate HeapNumbers from old space if they | 268 // that no GC is triggered, allocate HeapNumbers from old space if they |
282 // can't be taken from new space. | 269 // can't be taken from new space. |
283 if (!maybe_value->ToObject(&value)) { | 270 if (!maybe_value->ToObject(&value)) { |
284 ASSERT(maybe_value->IsRetryAfterGC() || maybe_value->IsOutOfMemory()); | 271 ASSERT(maybe_value->IsRetryAfterGC() || maybe_value->IsOutOfMemory()); |
285 Heap* heap = from->GetHeap(); | 272 Heap* heap = from->GetHeap(); |
286 MaybeObject* maybe_value_object = | 273 MaybeObject* maybe_value_object = |
287 heap->AllocateHeapNumber(from->get_scalar(i + from_start), | 274 heap->AllocateHeapNumber(from->get_scalar(i + from_start), |
288 TENURED); | 275 TENURED); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 class ElementsAccessorBase : public ElementsAccessor { | 397 class ElementsAccessorBase : public ElementsAccessor { |
411 protected: | 398 protected: |
412 explicit ElementsAccessorBase(const char* name) | 399 explicit ElementsAccessorBase(const char* name) |
413 : ElementsAccessor(name) { } | 400 : ElementsAccessor(name) { } |
414 | 401 |
415 typedef ElementsTraitsParam ElementsTraits; | 402 typedef ElementsTraitsParam ElementsTraits; |
416 typedef typename ElementsTraitsParam::BackingStore BackingStore; | 403 typedef typename ElementsTraitsParam::BackingStore BackingStore; |
417 | 404 |
418 virtual ElementsKind kind() const { return ElementsTraits::Kind; } | 405 virtual ElementsKind kind() const { return ElementsTraits::Kind; } |
419 | 406 |
420 static void ValidateContents(JSObject* holder, int length) { | |
421 } | |
422 | |
423 static void ValidateImpl(JSObject* holder) { | |
424 FixedArrayBase* fixed_array_base = holder->elements(); | |
425 // When objects are first allocated, its elements are Failures. | |
426 if (fixed_array_base->IsFailure()) return; | |
427 if (!fixed_array_base->IsHeapObject()) return; | |
428 Map* map = fixed_array_base->map(); | |
429 // Arrays that have been shifted in place can't be verified. | |
430 Heap* heap = holder->GetHeap(); | |
431 if (map == heap->raw_unchecked_one_pointer_filler_map() || | |
432 map == heap->raw_unchecked_two_pointer_filler_map() || | |
433 map == heap->free_space_map()) { | |
434 return; | |
435 } | |
436 int length = 0; | |
437 if (holder->IsJSArray()) { | |
438 Object* length_obj = JSArray::cast(holder)->length(); | |
439 if (length_obj->IsSmi()) { | |
440 length = Smi::cast(length_obj)->value(); | |
441 } | |
442 } else { | |
443 length = fixed_array_base->length(); | |
444 } | |
445 ElementsAccessorSubclass::ValidateContents(holder, length); | |
446 } | |
447 | |
448 virtual void Validate(JSObject* holder) { | |
449 ElementsAccessorSubclass::ValidateImpl(holder); | |
450 } | |
451 | |
452 static bool HasElementImpl(Object* receiver, | 407 static bool HasElementImpl(Object* receiver, |
453 JSObject* holder, | 408 JSObject* holder, |
454 uint32_t key, | 409 uint32_t key, |
455 BackingStore* backing_store) { | 410 BackingStore* backing_store) { |
456 MaybeObject* element = | 411 MaybeObject* element = |
457 ElementsAccessorSubclass::GetImpl(receiver, holder, key, backing_store); | 412 ElementsAccessorSubclass::GetImpl(receiver, holder, key, backing_store); |
458 return !element->IsTheHole(); | 413 return !element->IsTheHole(); |
459 } | 414 } |
460 | 415 |
461 virtual bool HasElement(Object* receiver, | 416 virtual bool HasElement(Object* receiver, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 Object* length) { | 448 Object* length) { |
494 return ElementsAccessorSubclass::SetLengthImpl( | 449 return ElementsAccessorSubclass::SetLengthImpl( |
495 array, length, BackingStore::cast(array->elements())); | 450 array, length, BackingStore::cast(array->elements())); |
496 } | 451 } |
497 | 452 |
498 MUST_USE_RESULT static MaybeObject* SetLengthImpl( | 453 MUST_USE_RESULT static MaybeObject* SetLengthImpl( |
499 JSObject* obj, | 454 JSObject* obj, |
500 Object* length, | 455 Object* length, |
501 BackingStore* backing_store); | 456 BackingStore* backing_store); |
502 | 457 |
503 MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength( | 458 MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength(JSArray* array, |
504 JSArray* array, | 459 int capacity, |
505 int capacity, | 460 int length) { |
506 int length) { | |
507 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( | 461 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( |
508 array, | 462 array, |
509 capacity, | 463 capacity, |
510 length); | 464 length); |
511 } | 465 } |
512 | 466 |
513 MUST_USE_RESULT static MaybeObject* SetFastElementsCapacityAndLength( | 467 MUST_USE_RESULT static MaybeObject* SetFastElementsCapacityAndLength( |
514 JSObject* obj, | 468 JSObject* obj, |
515 int capacity, | 469 int capacity, |
516 int length) { | 470 int length) { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
662 typename KindTraits, | 616 typename KindTraits, |
663 int ElementSize> | 617 int ElementSize> |
664 class FastElementsAccessor | 618 class FastElementsAccessor |
665 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { | 619 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { |
666 public: | 620 public: |
667 explicit FastElementsAccessor(const char* name) | 621 explicit FastElementsAccessor(const char* name) |
668 : ElementsAccessorBase<FastElementsAccessorSubclass, | 622 : ElementsAccessorBase<FastElementsAccessorSubclass, |
669 KindTraits>(name) {} | 623 KindTraits>(name) {} |
670 protected: | 624 protected: |
671 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; | 625 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; |
672 friend class NonStrictArgumentsElementsAccessor; | |
673 | 626 |
674 typedef typename KindTraits::BackingStore BackingStore; | 627 typedef typename KindTraits::BackingStore BackingStore; |
675 | 628 |
676 // Adjusts the length of the fast backing store or returns the new length or | 629 // Adjusts the length of the fast backing store or returns the new length or |
677 // undefined in case conversion to a slow backing store should be performed. | 630 // undefined in case conversion to a slow backing store should be performed. |
678 static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store, | 631 static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store, |
679 JSArray* array, | 632 JSArray* array, |
680 Object* length_object, | 633 Object* length_object, |
681 uint32_t length) { | 634 uint32_t length) { |
682 uint32_t old_capacity = backing_store->length(); | 635 uint32_t old_capacity = backing_store->length(); |
683 Object* old_length = array->length(); | |
684 bool same_size = old_length->IsSmi() && | |
685 static_cast<uint32_t>(Smi::cast(old_length)->value()) == length; | |
686 ElementsKind kind = array->GetElementsKind(); | |
687 | |
688 if (!same_size && IsFastElementsKind(kind) && | |
689 !IsFastHoleyElementsKind(kind)) { | |
690 kind = GetHoleyElementsKind(kind); | |
691 MaybeObject* maybe_obj = array->TransitionElementsKind(kind); | |
692 if (maybe_obj->IsFailure()) return maybe_obj; | |
693 } | |
694 | 636 |
695 // Check whether the backing store should be shrunk. | 637 // Check whether the backing store should be shrunk. |
696 if (length <= old_capacity) { | 638 if (length <= old_capacity) { |
697 if (array->HasFastSmiOrObjectElements()) { | 639 if (array->HasFastTypeElements()) { |
698 MaybeObject* maybe_obj = array->EnsureWritableFastElements(); | 640 MaybeObject* maybe_obj = array->EnsureWritableFastElements(); |
699 if (!maybe_obj->To(&backing_store)) return maybe_obj; | 641 if (!maybe_obj->To(&backing_store)) return maybe_obj; |
700 } | 642 } |
701 if (2 * length <= old_capacity) { | 643 if (2 * length <= old_capacity) { |
702 // If more than half the elements won't be used, trim the array. | 644 // If more than half the elements won't be used, trim the array. |
703 if (length == 0) { | 645 if (length == 0) { |
704 array->initialize_elements(); | 646 array->initialize_elements(); |
705 } else { | 647 } else { |
706 backing_store->set_length(length); | 648 backing_store->set_length(length); |
707 Address filler_start = backing_store->address() + | 649 Address filler_start = backing_store->address() + |
(...skipping 11 matching lines...) Expand all Loading... |
719 return length_object; | 661 return length_object; |
720 } | 662 } |
721 | 663 |
722 // Check whether the backing store should be expanded. | 664 // Check whether the backing store should be expanded. |
723 uint32_t min = JSObject::NewElementsCapacity(old_capacity); | 665 uint32_t min = JSObject::NewElementsCapacity(old_capacity); |
724 uint32_t new_capacity = length > min ? length : min; | 666 uint32_t new_capacity = length > min ? length : min; |
725 if (!array->ShouldConvertToSlowElements(new_capacity)) { | 667 if (!array->ShouldConvertToSlowElements(new_capacity)) { |
726 MaybeObject* result = FastElementsAccessorSubclass:: | 668 MaybeObject* result = FastElementsAccessorSubclass:: |
727 SetFastElementsCapacityAndLength(array, new_capacity, length); | 669 SetFastElementsCapacityAndLength(array, new_capacity, length); |
728 if (result->IsFailure()) return result; | 670 if (result->IsFailure()) return result; |
729 array->ValidateElements(); | |
730 return length_object; | 671 return length_object; |
731 } | 672 } |
732 | 673 |
733 // Request conversion to slow elements. | 674 // Request conversion to slow elements. |
734 return array->GetHeap()->undefined_value(); | 675 return array->GetHeap()->undefined_value(); |
735 } | 676 } |
| 677 }; |
| 678 |
| 679 |
| 680 class FastObjectElementsAccessor |
| 681 : public FastElementsAccessor<FastObjectElementsAccessor, |
| 682 ElementsKindTraits<FAST_ELEMENTS>, |
| 683 kPointerSize> { |
| 684 public: |
| 685 explicit FastObjectElementsAccessor(const char* name) |
| 686 : FastElementsAccessor<FastObjectElementsAccessor, |
| 687 ElementsKindTraits<FAST_ELEMENTS>, |
| 688 kPointerSize>(name) {} |
736 | 689 |
737 static MaybeObject* DeleteCommon(JSObject* obj, | 690 static MaybeObject* DeleteCommon(JSObject* obj, |
738 uint32_t key, | 691 uint32_t key) { |
739 JSReceiver::DeleteMode mode) { | 692 ASSERT(obj->HasFastElements() || |
740 ASSERT(obj->HasFastSmiOrObjectElements() || | 693 obj->HasFastSmiOnlyElements() || |
741 obj->HasFastDoubleElements() || | |
742 obj->HasFastArgumentsElements()); | 694 obj->HasFastArgumentsElements()); |
743 typename KindTraits::BackingStore* backing_store = | |
744 KindTraits::BackingStore::cast(obj->elements()); | |
745 Heap* heap = obj->GetHeap(); | 695 Heap* heap = obj->GetHeap(); |
| 696 FixedArray* backing_store = FixedArray::cast(obj->elements()); |
746 if (backing_store->map() == heap->non_strict_arguments_elements_map()) { | 697 if (backing_store->map() == heap->non_strict_arguments_elements_map()) { |
747 backing_store = | 698 backing_store = FixedArray::cast(backing_store->get(1)); |
748 KindTraits::BackingStore::cast( | |
749 FixedArray::cast(backing_store)->get(1)); | |
750 } else { | 699 } else { |
751 ElementsKind kind = KindTraits::Kind; | 700 Object* writable; |
752 if (IsFastPackedElementsKind(kind)) { | 701 MaybeObject* maybe = obj->EnsureWritableFastElements(); |
753 MaybeObject* transitioned = | 702 if (!maybe->ToObject(&writable)) return maybe; |
754 obj->TransitionElementsKind(GetHoleyElementsKind(kind)); | 703 backing_store = FixedArray::cast(writable); |
755 if (transitioned->IsFailure()) return transitioned; | |
756 } | |
757 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) { | |
758 Object* writable; | |
759 MaybeObject* maybe = obj->EnsureWritableFastElements(); | |
760 if (!maybe->ToObject(&writable)) return maybe; | |
761 backing_store = KindTraits::BackingStore::cast(writable); | |
762 } | |
763 } | 704 } |
764 uint32_t length = static_cast<uint32_t>( | 705 uint32_t length = static_cast<uint32_t>( |
765 obj->IsJSArray() | 706 obj->IsJSArray() |
766 ? Smi::cast(JSArray::cast(obj)->length())->value() | 707 ? Smi::cast(JSArray::cast(obj)->length())->value() |
767 : backing_store->length()); | 708 : backing_store->length()); |
768 if (key < length) { | 709 if (key < length) { |
769 backing_store->set_the_hole(key); | 710 backing_store->set_the_hole(key); |
770 // If an old space backing store is larger than a certain size and | 711 // If an old space backing store is larger than a certain size and |
771 // has too few used values, normalize it. | 712 // has too few used values, normalize it. |
772 // To avoid doing the check on every delete we require at least | 713 // To avoid doing the check on every delete we require at least |
773 // one adjacent hole to the value being deleted. | 714 // one adjacent hole to the value being deleted. |
| 715 Object* hole = heap->the_hole_value(); |
774 const int kMinLengthForSparsenessCheck = 64; | 716 const int kMinLengthForSparsenessCheck = 64; |
775 if (backing_store->length() >= kMinLengthForSparsenessCheck && | 717 if (backing_store->length() >= kMinLengthForSparsenessCheck && |
776 !heap->InNewSpace(backing_store) && | 718 !heap->InNewSpace(backing_store) && |
777 ((key > 0 && backing_store->is_the_hole(key - 1)) || | 719 ((key > 0 && backing_store->get(key - 1) == hole) || |
778 (key + 1 < length && backing_store->is_the_hole(key + 1)))) { | 720 (key + 1 < length && backing_store->get(key + 1) == hole))) { |
779 int num_used = 0; | 721 int num_used = 0; |
780 for (int i = 0; i < backing_store->length(); ++i) { | 722 for (int i = 0; i < backing_store->length(); ++i) { |
781 if (!backing_store->is_the_hole(i)) ++num_used; | 723 if (backing_store->get(i) != hole) ++num_used; |
782 // Bail out early if more than 1/4 is used. | 724 // Bail out early if more than 1/4 is used. |
783 if (4 * num_used > backing_store->length()) break; | 725 if (4 * num_used > backing_store->length()) break; |
784 } | 726 } |
785 if (4 * num_used <= backing_store->length()) { | 727 if (4 * num_used <= backing_store->length()) { |
786 MaybeObject* result = obj->NormalizeElements(); | 728 MaybeObject* result = obj->NormalizeElements(); |
787 if (result->IsFailure()) return result; | 729 if (result->IsFailure()) return result; |
788 } | 730 } |
789 } | 731 } |
790 } | 732 } |
791 return heap->true_value(); | 733 return heap->true_value(); |
792 } | 734 } |
793 | 735 |
794 virtual MaybeObject* Delete(JSObject* obj, | |
795 uint32_t key, | |
796 JSReceiver::DeleteMode mode) { | |
797 return DeleteCommon(obj, key, mode); | |
798 } | |
799 | |
800 static bool HasElementImpl( | |
801 Object* receiver, | |
802 JSObject* holder, | |
803 uint32_t key, | |
804 typename KindTraits::BackingStore* backing_store) { | |
805 if (key >= static_cast<uint32_t>(backing_store->length())) { | |
806 return false; | |
807 } | |
808 return !backing_store->is_the_hole(key); | |
809 } | |
810 | |
811 static void ValidateContents(JSObject* holder, int length) { | |
812 #if DEBUG | |
813 FixedArrayBase* elements = holder->elements(); | |
814 Heap* heap = elements->GetHeap(); | |
815 Map* map = elements->map(); | |
816 ASSERT((IsFastSmiOrObjectElementsKind(KindTraits::Kind) && | |
817 (map == heap->fixed_array_map() || | |
818 map == heap->fixed_cow_array_map())) || | |
819 (IsFastDoubleElementsKind(KindTraits::Kind) == | |
820 ((map == heap->fixed_array_map() && length == 0) || | |
821 map == heap->fixed_double_array_map()))); | |
822 for (int i = 0; i < length; i++) { | |
823 typename KindTraits::BackingStore* backing_store = | |
824 KindTraits::BackingStore::cast(elements); | |
825 ASSERT((!IsFastSmiElementsKind(KindTraits::Kind) || | |
826 static_cast<Object*>(backing_store->get(i))->IsSmi()) || | |
827 (IsFastHoleyElementsKind(KindTraits::Kind) == | |
828 backing_store->is_the_hole(i))); | |
829 } | |
830 #endif | |
831 } | |
832 }; | |
833 | |
834 | |
835 template<typename FastElementsAccessorSubclass, | |
836 typename KindTraits> | |
837 class FastSmiOrObjectElementsAccessor | |
838 : public FastElementsAccessor<FastElementsAccessorSubclass, | |
839 KindTraits, | |
840 kPointerSize> { | |
841 public: | |
842 explicit FastSmiOrObjectElementsAccessor(const char* name) | |
843 : FastElementsAccessor<FastElementsAccessorSubclass, | |
844 KindTraits, | |
845 kPointerSize>(name) {} | |
846 | |
847 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 736 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
848 uint32_t from_start, | 737 uint32_t from_start, |
849 FixedArrayBase* to, | 738 FixedArrayBase* to, |
850 ElementsKind to_kind, | 739 ElementsKind to_kind, |
851 uint32_t to_start, | 740 uint32_t to_start, |
852 int copy_size) { | 741 int copy_size) { |
853 if (IsFastSmiOrObjectElementsKind(to_kind)) { | 742 switch (to_kind) { |
854 CopyObjectToObjectElements( | 743 case FAST_SMI_ONLY_ELEMENTS: |
855 FixedArray::cast(from), KindTraits::Kind, from_start, | 744 case FAST_ELEMENTS: { |
856 FixedArray::cast(to), to_kind, to_start, copy_size); | 745 CopyObjectToObjectElements( |
857 } else if (IsFastDoubleElementsKind(to_kind)) { | 746 FixedArray::cast(from), ElementsTraits::Kind, from_start, |
858 CopyObjectToDoubleElements( | 747 FixedArray::cast(to), to_kind, to_start, copy_size); |
859 FixedArray::cast(from), from_start, | 748 return from; |
860 FixedDoubleArray::cast(to), to_start, copy_size); | 749 } |
861 } else { | 750 case FAST_DOUBLE_ELEMENTS: |
862 UNREACHABLE(); | 751 CopyObjectToDoubleElements( |
| 752 FixedArray::cast(from), from_start, |
| 753 FixedDoubleArray::cast(to), to_start, copy_size); |
| 754 return from; |
| 755 default: |
| 756 UNREACHABLE(); |
863 } | 757 } |
864 return to->GetHeap()->undefined_value(); | 758 return to->GetHeap()->undefined_value(); |
865 } | 759 } |
866 | 760 |
867 | 761 |
868 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | 762 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, |
869 uint32_t capacity, | 763 uint32_t capacity, |
870 uint32_t length) { | 764 uint32_t length) { |
871 JSObject::SetFastElementsCapacitySmiMode set_capacity_mode = | 765 JSObject::SetFastElementsCapacityMode set_capacity_mode = |
872 obj->HasFastSmiElements() | 766 obj->HasFastSmiOnlyElements() |
873 ? JSObject::kAllowSmiElements | 767 ? JSObject::kAllowSmiOnlyElements |
874 : JSObject::kDontAllowSmiElements; | 768 : JSObject::kDontAllowSmiOnlyElements; |
875 return obj->SetFastElementsCapacityAndLength(capacity, | 769 return obj->SetFastElementsCapacityAndLength(capacity, |
876 length, | 770 length, |
877 set_capacity_mode); | 771 set_capacity_mode); |
878 } | 772 } |
| 773 |
| 774 protected: |
| 775 friend class FastElementsAccessor<FastObjectElementsAccessor, |
| 776 ElementsKindTraits<FAST_ELEMENTS>, |
| 777 kPointerSize>; |
| 778 |
| 779 virtual MaybeObject* Delete(JSObject* obj, |
| 780 uint32_t key, |
| 781 JSReceiver::DeleteMode mode) { |
| 782 return DeleteCommon(obj, key); |
| 783 } |
879 }; | 784 }; |
880 | 785 |
881 | 786 |
882 class FastPackedSmiElementsAccessor | |
883 : public FastSmiOrObjectElementsAccessor< | |
884 FastPackedSmiElementsAccessor, | |
885 ElementsKindTraits<FAST_SMI_ELEMENTS> > { | |
886 public: | |
887 explicit FastPackedSmiElementsAccessor(const char* name) | |
888 : FastSmiOrObjectElementsAccessor< | |
889 FastPackedSmiElementsAccessor, | |
890 ElementsKindTraits<FAST_SMI_ELEMENTS> >(name) {} | |
891 }; | |
892 | |
893 | |
894 class FastHoleySmiElementsAccessor | |
895 : public FastSmiOrObjectElementsAccessor< | |
896 FastHoleySmiElementsAccessor, | |
897 ElementsKindTraits<FAST_HOLEY_SMI_ELEMENTS> > { | |
898 public: | |
899 explicit FastHoleySmiElementsAccessor(const char* name) | |
900 : FastSmiOrObjectElementsAccessor< | |
901 FastHoleySmiElementsAccessor, | |
902 ElementsKindTraits<FAST_HOLEY_SMI_ELEMENTS> >(name) {} | |
903 }; | |
904 | |
905 | |
906 class FastPackedObjectElementsAccessor | |
907 : public FastSmiOrObjectElementsAccessor< | |
908 FastPackedObjectElementsAccessor, | |
909 ElementsKindTraits<FAST_ELEMENTS> > { | |
910 public: | |
911 explicit FastPackedObjectElementsAccessor(const char* name) | |
912 : FastSmiOrObjectElementsAccessor< | |
913 FastPackedObjectElementsAccessor, | |
914 ElementsKindTraits<FAST_ELEMENTS> >(name) {} | |
915 }; | |
916 | |
917 | |
918 class FastHoleyObjectElementsAccessor | |
919 : public FastSmiOrObjectElementsAccessor< | |
920 FastHoleyObjectElementsAccessor, | |
921 ElementsKindTraits<FAST_HOLEY_ELEMENTS> > { | |
922 public: | |
923 explicit FastHoleyObjectElementsAccessor(const char* name) | |
924 : FastSmiOrObjectElementsAccessor< | |
925 FastHoleyObjectElementsAccessor, | |
926 ElementsKindTraits<FAST_HOLEY_ELEMENTS> >(name) {} | |
927 }; | |
928 | |
929 | |
930 template<typename FastElementsAccessorSubclass, | |
931 typename KindTraits> | |
932 class FastDoubleElementsAccessor | 787 class FastDoubleElementsAccessor |
933 : public FastElementsAccessor<FastElementsAccessorSubclass, | 788 : public FastElementsAccessor<FastDoubleElementsAccessor, |
934 KindTraits, | 789 ElementsKindTraits<FAST_DOUBLE_ELEMENTS>, |
935 kDoubleSize> { | 790 kDoubleSize> { |
936 public: | 791 public: |
937 explicit FastDoubleElementsAccessor(const char* name) | 792 explicit FastDoubleElementsAccessor(const char* name) |
938 : FastElementsAccessor<FastElementsAccessorSubclass, | 793 : FastElementsAccessor<FastDoubleElementsAccessor, |
939 KindTraits, | 794 ElementsKindTraits<FAST_DOUBLE_ELEMENTS>, |
940 kDoubleSize>(name) {} | 795 kDoubleSize>(name) {} |
941 | 796 |
942 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | 797 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, |
943 uint32_t capacity, | 798 uint32_t capacity, |
944 uint32_t length) { | 799 uint32_t length) { |
945 return obj->SetFastDoubleElementsCapacityAndLength(capacity, | 800 return obj->SetFastDoubleElementsCapacityAndLength(capacity, length); |
946 length); | |
947 } | 801 } |
948 | 802 |
949 protected: | 803 protected: |
| 804 friend class ElementsAccessorBase<FastDoubleElementsAccessor, |
| 805 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >; |
| 806 friend class FastElementsAccessor<FastDoubleElementsAccessor, |
| 807 ElementsKindTraits<FAST_DOUBLE_ELEMENTS>, |
| 808 kDoubleSize>; |
| 809 |
950 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 810 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
951 uint32_t from_start, | 811 uint32_t from_start, |
952 FixedArrayBase* to, | 812 FixedArrayBase* to, |
953 ElementsKind to_kind, | 813 ElementsKind to_kind, |
954 uint32_t to_start, | 814 uint32_t to_start, |
955 int copy_size) { | 815 int copy_size) { |
956 switch (to_kind) { | 816 switch (to_kind) { |
957 case FAST_SMI_ELEMENTS: | 817 case FAST_SMI_ONLY_ELEMENTS: |
958 case FAST_ELEMENTS: | 818 case FAST_ELEMENTS: |
959 case FAST_HOLEY_SMI_ELEMENTS: | |
960 case FAST_HOLEY_ELEMENTS: | |
961 return CopyDoubleToObjectElements( | 819 return CopyDoubleToObjectElements( |
962 FixedDoubleArray::cast(from), from_start, FixedArray::cast(to), | 820 FixedDoubleArray::cast(from), from_start, FixedArray::cast(to), |
963 to_kind, to_start, copy_size); | 821 to_kind, to_start, copy_size); |
964 case FAST_DOUBLE_ELEMENTS: | 822 case FAST_DOUBLE_ELEMENTS: |
965 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
966 CopyDoubleToDoubleElements(FixedDoubleArray::cast(from), from_start, | 823 CopyDoubleToDoubleElements(FixedDoubleArray::cast(from), from_start, |
967 FixedDoubleArray::cast(to), | 824 FixedDoubleArray::cast(to), |
968 to_start, copy_size); | 825 to_start, copy_size); |
969 return from; | 826 return from; |
970 default: | 827 default: |
971 UNREACHABLE(); | 828 UNREACHABLE(); |
972 } | 829 } |
973 return to->GetHeap()->undefined_value(); | 830 return to->GetHeap()->undefined_value(); |
974 } | 831 } |
| 832 |
| 833 virtual MaybeObject* Delete(JSObject* obj, |
| 834 uint32_t key, |
| 835 JSReceiver::DeleteMode mode) { |
| 836 int length = obj->IsJSArray() |
| 837 ? Smi::cast(JSArray::cast(obj)->length())->value() |
| 838 : FixedDoubleArray::cast(obj->elements())->length(); |
| 839 if (key < static_cast<uint32_t>(length)) { |
| 840 FixedDoubleArray::cast(obj->elements())->set_the_hole(key); |
| 841 } |
| 842 return obj->GetHeap()->true_value(); |
| 843 } |
| 844 |
| 845 static bool HasElementImpl(Object* receiver, |
| 846 JSObject* holder, |
| 847 uint32_t key, |
| 848 FixedDoubleArray* backing_store) { |
| 849 return key < static_cast<uint32_t>(backing_store->length()) && |
| 850 !backing_store->is_the_hole(key); |
| 851 } |
975 }; | 852 }; |
976 | 853 |
977 | 854 |
978 class FastPackedDoubleElementsAccessor | |
979 : public FastDoubleElementsAccessor< | |
980 FastPackedDoubleElementsAccessor, | |
981 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> > { | |
982 public: | |
983 friend class ElementsAccessorBase<FastPackedDoubleElementsAccessor, | |
984 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >; | |
985 explicit FastPackedDoubleElementsAccessor(const char* name) | |
986 : FastDoubleElementsAccessor< | |
987 FastPackedDoubleElementsAccessor, | |
988 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >(name) {} | |
989 }; | |
990 | |
991 | |
992 class FastHoleyDoubleElementsAccessor | |
993 : public FastDoubleElementsAccessor< | |
994 FastHoleyDoubleElementsAccessor, | |
995 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > { | |
996 public: | |
997 friend class ElementsAccessorBase< | |
998 FastHoleyDoubleElementsAccessor, | |
999 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >; | |
1000 explicit FastHoleyDoubleElementsAccessor(const char* name) | |
1001 : FastDoubleElementsAccessor< | |
1002 FastHoleyDoubleElementsAccessor, | |
1003 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {} | |
1004 }; | |
1005 | |
1006 | |
1007 // Super class for all external element arrays. | 855 // Super class for all external element arrays. |
1008 template<typename ExternalElementsAccessorSubclass, | 856 template<typename ExternalElementsAccessorSubclass, |
1009 ElementsKind Kind> | 857 ElementsKind Kind> |
1010 class ExternalElementsAccessor | 858 class ExternalElementsAccessor |
1011 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, | 859 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, |
1012 ElementsKindTraits<Kind> > { | 860 ElementsKindTraits<Kind> > { |
1013 public: | 861 public: |
1014 explicit ExternalElementsAccessor(const char* name) | 862 explicit ExternalElementsAccessor(const char* name) |
1015 : ElementsAccessorBase<ExternalElementsAccessorSubclass, | 863 : ElementsAccessorBase<ExternalElementsAccessorSubclass, |
1016 ElementsKindTraits<Kind> >(name) {} | 864 ElementsKindTraits<Kind> >(name) {} |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1260 return heap->true_value(); | 1108 return heap->true_value(); |
1261 } | 1109 } |
1262 | 1110 |
1263 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 1111 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
1264 uint32_t from_start, | 1112 uint32_t from_start, |
1265 FixedArrayBase* to, | 1113 FixedArrayBase* to, |
1266 ElementsKind to_kind, | 1114 ElementsKind to_kind, |
1267 uint32_t to_start, | 1115 uint32_t to_start, |
1268 int copy_size) { | 1116 int copy_size) { |
1269 switch (to_kind) { | 1117 switch (to_kind) { |
1270 case FAST_SMI_ELEMENTS: | 1118 case FAST_SMI_ONLY_ELEMENTS: |
1271 case FAST_ELEMENTS: | 1119 case FAST_ELEMENTS: |
1272 case FAST_HOLEY_SMI_ELEMENTS: | |
1273 case FAST_HOLEY_ELEMENTS: | |
1274 CopyDictionaryToObjectElements( | 1120 CopyDictionaryToObjectElements( |
1275 SeededNumberDictionary::cast(from), from_start, | 1121 SeededNumberDictionary::cast(from), from_start, |
1276 FixedArray::cast(to), to_kind, to_start, copy_size); | 1122 FixedArray::cast(to), to_kind, to_start, copy_size); |
1277 return from; | 1123 return from; |
1278 case FAST_DOUBLE_ELEMENTS: | 1124 case FAST_DOUBLE_ELEMENTS: |
1279 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
1280 CopyDictionaryToDoubleElements( | 1125 CopyDictionaryToDoubleElements( |
1281 SeededNumberDictionary::cast(from), from_start, | 1126 SeededNumberDictionary::cast(from), from_start, |
1282 FixedDoubleArray::cast(to), to_start, copy_size); | 1127 FixedDoubleArray::cast(to), to_start, copy_size); |
1283 return from; | 1128 return from; |
1284 default: | 1129 default: |
1285 UNREACHABLE(); | 1130 UNREACHABLE(); |
1286 } | 1131 } |
1287 return to->GetHeap()->undefined_value(); | 1132 return to->GetHeap()->undefined_value(); |
1288 } | 1133 } |
1289 | 1134 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 if (!probe->IsTheHole()) { | 1241 if (!probe->IsTheHole()) { |
1397 // TODO(kmillikin): We could check if this was the last aliased | 1242 // TODO(kmillikin): We could check if this was the last aliased |
1398 // parameter, and revert to normal elements in that case. That | 1243 // parameter, and revert to normal elements in that case. That |
1399 // would enable GC of the context. | 1244 // would enable GC of the context. |
1400 parameter_map->set_the_hole(key + 2); | 1245 parameter_map->set_the_hole(key + 2); |
1401 } else { | 1246 } else { |
1402 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1247 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1403 if (arguments->IsDictionary()) { | 1248 if (arguments->IsDictionary()) { |
1404 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode); | 1249 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode); |
1405 } else { | 1250 } else { |
1406 // It's difficult to access the version of DeleteCommon that is declared | 1251 return FastObjectElementsAccessor::DeleteCommon(obj, key); |
1407 // in the templatized super class, call the concrete implementation in | |
1408 // the class for the most generalized ElementsKind subclass. | |
1409 return FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, mode); | |
1410 } | 1252 } |
1411 } | 1253 } |
1412 return obj->GetHeap()->true_value(); | 1254 return obj->GetHeap()->true_value(); |
1413 } | 1255 } |
1414 | 1256 |
1415 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 1257 MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
1416 uint32_t from_start, | 1258 uint32_t from_start, |
1417 FixedArrayBase* to, | 1259 FixedArrayBase* to, |
1418 ElementsKind to_kind, | 1260 ElementsKind to_kind, |
1419 uint32_t to_start, | 1261 uint32_t to_start, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1463 } | 1305 } |
1464 }; | 1306 }; |
1465 | 1307 |
1466 | 1308 |
1467 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { | 1309 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { |
1468 switch (array->map()->instance_type()) { | 1310 switch (array->map()->instance_type()) { |
1469 case FIXED_ARRAY_TYPE: | 1311 case FIXED_ARRAY_TYPE: |
1470 if (array->IsDictionary()) { | 1312 if (array->IsDictionary()) { |
1471 return elements_accessors_[DICTIONARY_ELEMENTS]; | 1313 return elements_accessors_[DICTIONARY_ELEMENTS]; |
1472 } else { | 1314 } else { |
1473 return elements_accessors_[FAST_HOLEY_ELEMENTS]; | 1315 return elements_accessors_[FAST_ELEMENTS]; |
1474 } | 1316 } |
1475 case EXTERNAL_BYTE_ARRAY_TYPE: | 1317 case EXTERNAL_BYTE_ARRAY_TYPE: |
1476 return elements_accessors_[EXTERNAL_BYTE_ELEMENTS]; | 1318 return elements_accessors_[EXTERNAL_BYTE_ELEMENTS]; |
1477 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: | 1319 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: |
1478 return elements_accessors_[EXTERNAL_UNSIGNED_BYTE_ELEMENTS]; | 1320 return elements_accessors_[EXTERNAL_UNSIGNED_BYTE_ELEMENTS]; |
1479 case EXTERNAL_SHORT_ARRAY_TYPE: | 1321 case EXTERNAL_SHORT_ARRAY_TYPE: |
1480 return elements_accessors_[EXTERNAL_SHORT_ELEMENTS]; | 1322 return elements_accessors_[EXTERNAL_SHORT_ELEMENTS]; |
1481 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: | 1323 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: |
1482 return elements_accessors_[EXTERNAL_UNSIGNED_SHORT_ELEMENTS]; | 1324 return elements_accessors_[EXTERNAL_UNSIGNED_SHORT_ELEMENTS]; |
1483 case EXTERNAL_INT_ARRAY_TYPE: | 1325 case EXTERNAL_INT_ARRAY_TYPE: |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1574 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; | 1416 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; |
1575 new_backing_store->set(0, length); | 1417 new_backing_store->set(0, length); |
1576 { MaybeObject* result = array->SetContent(new_backing_store); | 1418 { MaybeObject* result = array->SetContent(new_backing_store); |
1577 if (result->IsFailure()) return result; | 1419 if (result->IsFailure()) return result; |
1578 } | 1420 } |
1579 return array; | 1421 return array; |
1580 } | 1422 } |
1581 | 1423 |
1582 | 1424 |
1583 } } // namespace v8::internal | 1425 } } // namespace v8::internal |
OLD | NEW |