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