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 // - 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...) Expand 10 before | Expand all | Expand 10 after 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); | 154 ASSERT(IsFastSmiOrObjectElementsKind(from_kind)); |
143 ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS); | 155 ASSERT(IsFastSmiOrObjectElementsKind(to_kind)); |
144 int copy_size = raw_copy_size; | 156 int copy_size = raw_copy_size; |
145 if (raw_copy_size < 0) { | 157 if (raw_copy_size < 0) { |
146 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || | 158 ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd || |
147 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); | 159 raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole); |
148 copy_size = Min(from->length() - from_start, | 160 copy_size = Min(from->length() - from_start, |
149 to->length() - to_start); | 161 to->length() - to_start); |
150 #ifdef DEBUG | 162 #ifdef DEBUG |
151 // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already | 163 // FAST_*_ELEMENTS arrays cannot be uninitialized. Ensure they are already |
152 // marked with the hole. | 164 // marked with the hole. |
153 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { | 165 if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) { |
154 for (int i = to_start + copy_size; i < to->length(); ++i) { | 166 for (int i = to_start + copy_size; i < to->length(); ++i) { |
155 ASSERT(to->get(i)->IsTheHole()); | 167 ASSERT(to->get(i)->IsTheHole()); |
156 } | 168 } |
157 } | 169 } |
158 #endif | 170 #endif |
159 } | 171 } |
160 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && | 172 ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() && |
161 (copy_size + static_cast<int>(from_start)) <= from->length()); | 173 (copy_size + static_cast<int>(from_start)) <= from->length()); |
162 if (copy_size == 0) return; | 174 if (copy_size == 0) return; |
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...) Expand 10 before | Expand all | Expand 10 after 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 30 matching lines...) Expand all Loading... | |
447 virtual MaybeObject* SetLength(JSArray* array, | 492 virtual MaybeObject* SetLength(JSArray* array, |
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 static MaybeObject* SetLengthImpl(JSObject* obj, | 498 static MaybeObject* SetLengthImpl(JSObject* obj, |
454 Object* length, | 499 Object* length, |
455 BackingStore* backing_store); | 500 BackingStore* backing_store); |
456 | 501 |
457 virtual MaybeObject* SetCapacityAndLength(JSArray* array, | 502 virtual MaybeObject* SetCapacityAndLength( |
Jakob Kummerow
2012/05/13 21:55:27
nit: both this and the following change seem unnec
danno
2012/05/22 11:05:21
Done.
| |
458 int capacity, | 503 JSArray* array, |
459 int length) { | 504 int capacity, |
505 int length) { | |
460 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( | 506 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( |
461 array, | 507 array, |
462 capacity, | 508 capacity, |
463 length); | 509 length); |
464 } | 510 } |
465 | 511 |
466 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | 512 static MaybeObject* SetFastElementsCapacityAndLength( |
467 int capacity, | 513 JSObject* obj, |
468 int length) { | 514 int capacity, |
515 int length) { | |
469 UNIMPLEMENTED(); | 516 UNIMPLEMENTED(); |
470 return obj; | 517 return obj; |
471 } | 518 } |
472 | 519 |
473 virtual MaybeObject* Delete(JSObject* obj, | 520 virtual MaybeObject* Delete(JSObject* obj, |
474 uint32_t key, | 521 uint32_t key, |
475 JSReceiver::DeleteMode mode) = 0; | 522 JSReceiver::DeleteMode mode) = 0; |
476 | 523 |
477 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 524 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
478 uint32_t from_start, | 525 uint32_t from_start, |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
613 typename KindTraits, | 660 typename KindTraits, |
614 int ElementSize> | 661 int ElementSize> |
615 class FastElementsAccessor | 662 class FastElementsAccessor |
616 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { | 663 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { |
617 public: | 664 public: |
618 explicit FastElementsAccessor(const char* name) | 665 explicit FastElementsAccessor(const char* name) |
619 : ElementsAccessorBase<FastElementsAccessorSubclass, | 666 : ElementsAccessorBase<FastElementsAccessorSubclass, |
620 KindTraits>(name) {} | 667 KindTraits>(name) {} |
621 protected: | 668 protected: |
622 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; | 669 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; |
670 friend class NonStrictArgumentsElementsAccessor; | |
623 | 671 |
624 typedef typename KindTraits::BackingStore BackingStore; | 672 typedef typename KindTraits::BackingStore BackingStore; |
625 | 673 |
626 // Adjusts the length of the fast backing store or returns the new length or | 674 // Adjusts the length of the fast backing store or returns the new length or |
627 // undefined in case conversion to a slow backing store should be performed. | 675 // undefined in case conversion to a slow backing store should be performed. |
628 static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store, | 676 static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store, |
629 JSArray* array, | 677 JSArray* array, |
630 Object* length_object, | 678 Object* length_object, |
631 uint32_t length) { | 679 uint32_t length) { |
632 uint32_t old_capacity = backing_store->length(); | 680 uint32_t old_capacity = backing_store->length(); |
681 Object* old_length = array->length(); | |
682 bool same_size = old_length->IsSmi() && | |
683 static_cast<uint32_t>(Smi::cast(old_length)->value()) == length; | |
684 ElementsKind kind = array->GetElementsKind(); | |
685 | |
686 if (!same_size && IsFastElementsKind(kind) && | |
687 !IsFastHoleyElementsKind(kind)) { | |
688 kind = GetHoleyElementsKind(kind); | |
689 MaybeObject* maybe_obj = array->TransitionElementsKind(kind); | |
690 if (maybe_obj->IsFailure()) return maybe_obj; | |
691 } | |
633 | 692 |
634 // Check whether the backing store should be shrunk. | 693 // Check whether the backing store should be shrunk. |
635 if (length <= old_capacity) { | 694 if (length <= old_capacity) { |
636 if (array->HasFastTypeElements()) { | 695 if (array->HasFastSmiOrObjectElements()) { |
637 MaybeObject* maybe_obj = array->EnsureWritableFastElements(); | 696 MaybeObject* maybe_obj = array->EnsureWritableFastElements(); |
638 if (!maybe_obj->To(&backing_store)) return maybe_obj; | 697 if (!maybe_obj->To(&backing_store)) return maybe_obj; |
639 } | 698 } |
640 if (2 * length <= old_capacity) { | 699 if (2 * length <= old_capacity) { |
641 // If more than half the elements won't be used, trim the array. | 700 // If more than half the elements won't be used, trim the array. |
642 if (length == 0) { | 701 if (length == 0) { |
643 array->initialize_elements(); | 702 array->initialize_elements(); |
644 } else { | 703 } else { |
645 backing_store->set_length(length); | 704 backing_store->set_length(length); |
646 Address filler_start = backing_store->address() + | 705 Address filler_start = backing_store->address() + |
(...skipping 11 matching lines...) Expand all Loading... | |
658 return length_object; | 717 return length_object; |
659 } | 718 } |
660 | 719 |
661 // Check whether the backing store should be expanded. | 720 // Check whether the backing store should be expanded. |
662 uint32_t min = JSObject::NewElementsCapacity(old_capacity); | 721 uint32_t min = JSObject::NewElementsCapacity(old_capacity); |
663 uint32_t new_capacity = length > min ? length : min; | 722 uint32_t new_capacity = length > min ? length : min; |
664 if (!array->ShouldConvertToSlowElements(new_capacity)) { | 723 if (!array->ShouldConvertToSlowElements(new_capacity)) { |
665 MaybeObject* result = FastElementsAccessorSubclass:: | 724 MaybeObject* result = FastElementsAccessorSubclass:: |
666 SetFastElementsCapacityAndLength(array, new_capacity, length); | 725 SetFastElementsCapacityAndLength(array, new_capacity, length); |
667 if (result->IsFailure()) return result; | 726 if (result->IsFailure()) return result; |
727 array->ValidateElements(); | |
668 return length_object; | 728 return length_object; |
669 } | 729 } |
670 | 730 |
671 // Request conversion to slow elements. | 731 // Request conversion to slow elements. |
672 return array->GetHeap()->undefined_value(); | 732 return array->GetHeap()->undefined_value(); |
673 } | 733 } |
674 }; | |
675 | |
676 | |
677 class FastObjectElementsAccessor | |
678 : public FastElementsAccessor<FastObjectElementsAccessor, | |
679 ElementsKindTraits<FAST_ELEMENTS>, | |
680 kPointerSize> { | |
681 public: | |
682 explicit FastObjectElementsAccessor(const char* name) | |
683 : FastElementsAccessor<FastObjectElementsAccessor, | |
684 ElementsKindTraits<FAST_ELEMENTS>, | |
685 kPointerSize>(name) {} | |
686 | 734 |
687 static MaybeObject* DeleteCommon(JSObject* obj, | 735 static MaybeObject* DeleteCommon(JSObject* obj, |
688 uint32_t key) { | 736 uint32_t key, |
689 ASSERT(obj->HasFastElements() || | 737 JSReceiver::DeleteMode mode) { |
690 obj->HasFastSmiOnlyElements() || | 738 ASSERT(obj->HasFastSmiOrObjectElements() || |
739 obj->HasFastDoubleElements() || | |
691 obj->HasFastArgumentsElements()); | 740 obj->HasFastArgumentsElements()); |
741 typename KindTraits::BackingStore* backing_store = | |
742 KindTraits::BackingStore::cast(obj->elements()); | |
692 Heap* heap = obj->GetHeap(); | 743 Heap* heap = obj->GetHeap(); |
693 FixedArray* backing_store = FixedArray::cast(obj->elements()); | |
694 if (backing_store->map() == heap->non_strict_arguments_elements_map()) { | 744 if (backing_store->map() == heap->non_strict_arguments_elements_map()) { |
695 backing_store = FixedArray::cast(backing_store->get(1)); | 745 backing_store = |
746 KindTraits::BackingStore::cast( | |
747 FixedArray::cast(backing_store)->get(1)); | |
696 } else { | 748 } else { |
697 Object* writable; | 749 ElementsKind kind = KindTraits::Kind; |
698 MaybeObject* maybe = obj->EnsureWritableFastElements(); | 750 if (IsFastPackedElementsKind(kind)) { |
699 if (!maybe->ToObject(&writable)) return maybe; | 751 MaybeObject* transitioned = |
700 backing_store = FixedArray::cast(writable); | 752 obj->TransitionElementsKind(GetHoleyElementsKind(kind)); |
753 if (transitioned->IsFailure()) return transitioned; | |
754 } | |
755 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) { | |
756 Object* writable; | |
757 MaybeObject* maybe = obj->EnsureWritableFastElements(); | |
758 if (!maybe->ToObject(&writable)) return maybe; | |
759 backing_store = KindTraits::BackingStore::cast(writable); | |
760 } | |
701 } | 761 } |
702 uint32_t length = static_cast<uint32_t>( | 762 uint32_t length = static_cast<uint32_t>( |
703 obj->IsJSArray() | 763 obj->IsJSArray() |
704 ? Smi::cast(JSArray::cast(obj)->length())->value() | 764 ? Smi::cast(JSArray::cast(obj)->length())->value() |
705 : backing_store->length()); | 765 : backing_store->length()); |
706 if (key < length) { | 766 if (key < length) { |
707 backing_store->set_the_hole(key); | 767 backing_store->set_the_hole(key); |
708 // If an old space backing store is larger than a certain size and | 768 // If an old space backing store is larger than a certain size and |
709 // has too few used values, normalize it. | 769 // has too few used values, normalize it. |
710 // To avoid doing the check on every delete we require at least | 770 // To avoid doing the check on every delete we require at least |
711 // one adjacent hole to the value being deleted. | 771 // one adjacent hole to the value being deleted. |
712 Object* hole = heap->the_hole_value(); | |
713 const int kMinLengthForSparsenessCheck = 64; | 772 const int kMinLengthForSparsenessCheck = 64; |
714 if (backing_store->length() >= kMinLengthForSparsenessCheck && | 773 if (backing_store->length() >= kMinLengthForSparsenessCheck && |
715 !heap->InNewSpace(backing_store) && | 774 !heap->InNewSpace(backing_store) && |
716 ((key > 0 && backing_store->get(key - 1) == hole) || | 775 ((key > 0 && backing_store->is_the_hole(key - 1)) || |
717 (key + 1 < length && backing_store->get(key + 1) == hole))) { | 776 (key + 1 < length && backing_store->is_the_hole(key + 1)))) { |
718 int num_used = 0; | 777 int num_used = 0; |
719 for (int i = 0; i < backing_store->length(); ++i) { | 778 for (int i = 0; i < backing_store->length(); ++i) { |
720 if (backing_store->get(i) != hole) ++num_used; | 779 if (!backing_store->is_the_hole(i)) ++num_used; |
721 // Bail out early if more than 1/4 is used. | 780 // Bail out early if more than 1/4 is used. |
722 if (4 * num_used > backing_store->length()) break; | 781 if (4 * num_used > backing_store->length()) break; |
723 } | 782 } |
724 if (4 * num_used <= backing_store->length()) { | 783 if (4 * num_used <= backing_store->length()) { |
725 MaybeObject* result = obj->NormalizeElements(); | 784 MaybeObject* result = obj->NormalizeElements(); |
726 if (result->IsFailure()) return result; | 785 if (result->IsFailure()) return result; |
727 } | 786 } |
728 } | 787 } |
729 } | 788 } |
730 return heap->true_value(); | 789 return heap->true_value(); |
731 } | 790 } |
732 | 791 |
792 virtual MaybeObject* Delete(JSObject* obj, | |
793 uint32_t key, | |
794 JSReceiver::DeleteMode mode) { | |
795 return DeleteCommon(obj, key, mode); | |
796 } | |
797 | |
798 static bool HasElementImpl( | |
799 Object* receiver, | |
800 JSObject* holder, | |
801 uint32_t key, | |
802 typename KindTraits::BackingStore* backing_store) { | |
803 return key < static_cast<uint32_t>(backing_store->length()) && | |
804 !backing_store->is_the_hole(key); | |
805 } | |
806 | |
807 static void ValidateContents(JSObject* holder, int length) { | |
808 #if DEBUG | |
809 FixedArrayBase* elements = holder->elements(); | |
810 Heap* heap = elements->GetHeap(); | |
811 Map* map = elements->map(); | |
812 ASSERT((IsFastSmiOrObjectElementsKind(KindTraits::Kind) && | |
813 (map == heap->fixed_array_map() || | |
814 map == heap->fixed_cow_array_map())) || | |
815 (IsFastDoubleElementsKind(KindTraits::Kind) == | |
816 ((map == heap->fixed_array_map() && length == 0) || | |
817 map == heap->fixed_double_array_map()))); | |
818 for (int i = 0; i < length; i++) { | |
819 typename KindTraits::BackingStore* backing_store = | |
820 KindTraits::BackingStore::cast(elements); | |
821 ASSERT((!IsFastSmiElementsKind(KindTraits::Kind) || | |
822 static_cast<Object*>(backing_store->get(i))->IsSmi()) || | |
823 (IsFastHoleyElementsKind(KindTraits::Kind) == | |
824 backing_store->is_the_hole(i))); | |
825 } | |
826 #endif | |
827 } | |
828 }; | |
829 | |
830 | |
831 template<typename FastElementsAccessorSubclass, | |
832 typename KindTraits> | |
833 class FastSmiOrObjectElementsAccessor | |
834 : public FastElementsAccessor<FastElementsAccessorSubclass, | |
835 KindTraits, | |
836 kPointerSize> { | |
837 public: | |
838 explicit FastSmiOrObjectElementsAccessor(const char* name) | |
839 : FastElementsAccessor<FastElementsAccessorSubclass, | |
840 KindTraits, | |
841 kPointerSize>(name) {} | |
842 | |
733 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 843 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
734 uint32_t from_start, | 844 uint32_t from_start, |
735 FixedArrayBase* to, | 845 FixedArrayBase* to, |
736 ElementsKind to_kind, | 846 ElementsKind to_kind, |
737 uint32_t to_start, | 847 uint32_t to_start, |
738 int copy_size) { | 848 int copy_size) { |
739 switch (to_kind) { | 849 if (IsFastSmiOrObjectElementsKind(to_kind)) { |
740 case FAST_SMI_ONLY_ELEMENTS: | 850 CopyObjectToObjectElements( |
741 case FAST_ELEMENTS: { | 851 FixedArray::cast(from), KindTraits::Kind, from_start, |
742 CopyObjectToObjectElements( | 852 FixedArray::cast(to), to_kind, to_start, copy_size); |
743 FixedArray::cast(from), ElementsTraits::Kind, from_start, | 853 } else if (IsFastDoubleElementsKind(to_kind)) { |
744 FixedArray::cast(to), to_kind, to_start, copy_size); | 854 CopyObjectToDoubleElements( |
745 return from; | 855 FixedArray::cast(from), from_start, |
746 } | 856 FixedDoubleArray::cast(to), to_start, copy_size); |
747 case FAST_DOUBLE_ELEMENTS: | 857 } else { |
748 CopyObjectToDoubleElements( | 858 UNREACHABLE(); |
749 FixedArray::cast(from), from_start, | 859 } |
Jakob Kummerow
2012/05/13 21:55:27
nit: indentation
danno
2012/05/22 11:05:21
Done.
| |
750 FixedDoubleArray::cast(to), to_start, copy_size); | |
751 return from; | |
752 default: | |
753 UNREACHABLE(); | |
754 } | |
755 return to->GetHeap()->undefined_value(); | 860 return to->GetHeap()->undefined_value(); |
756 } | 861 } |
757 | 862 |
758 | 863 |
759 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | 864 static MaybeObject* SetFastElementsCapacityAndLength( |
760 uint32_t capacity, | 865 JSObject* obj, |
Jakob Kummerow
2012/05/13 21:55:27
nit: unnecessary formatting change?
danno
2012/05/22 11:05:21
Done.
| |
761 uint32_t length) { | 866 uint32_t capacity, |
762 JSObject::SetFastElementsCapacityMode set_capacity_mode = | 867 uint32_t length) { |
763 obj->HasFastSmiOnlyElements() | 868 JSObject::SetFastElementsCapacitySmiMode set_capacity_mode = |
869 obj->HasFastSmiElements() | |
764 ? JSObject::kAllowSmiOnlyElements | 870 ? JSObject::kAllowSmiOnlyElements |
765 : JSObject::kDontAllowSmiOnlyElements; | 871 : JSObject::kDontAllowSmiOnlyElements; |
766 return obj->SetFastElementsCapacityAndLength(capacity, | 872 return obj->SetFastElementsCapacityAndLength(capacity, |
767 length, | 873 length, |
768 set_capacity_mode); | 874 set_capacity_mode); |
769 } | 875 } |
770 | |
771 protected: | |
772 friend class FastElementsAccessor<FastObjectElementsAccessor, | |
773 ElementsKindTraits<FAST_ELEMENTS>, | |
774 kPointerSize>; | |
775 | |
776 virtual MaybeObject* Delete(JSObject* obj, | |
777 uint32_t key, | |
778 JSReceiver::DeleteMode mode) { | |
779 return DeleteCommon(obj, key); | |
780 } | |
781 }; | 876 }; |
782 | 877 |
783 | 878 |
879 class FastPackedSmiElementsAccessor | |
880 : public FastSmiOrObjectElementsAccessor< | |
881 FastPackedSmiElementsAccessor, | |
882 ElementsKindTraits<FAST_SMI_ELEMENTS> > { | |
883 public: | |
884 explicit FastPackedSmiElementsAccessor(const char* name) | |
885 : FastSmiOrObjectElementsAccessor< | |
886 FastPackedSmiElementsAccessor, | |
887 ElementsKindTraits<FAST_SMI_ELEMENTS> >(name) {} | |
888 }; | |
889 | |
Jakob Kummerow
2012/05/13 21:55:27
nit: two empty lines (several more times below)
danno
2012/05/22 11:05:21
Done.
| |
890 class FastHoleySmiElementsAccessor | |
891 : public FastSmiOrObjectElementsAccessor< | |
892 FastHoleySmiElementsAccessor, | |
893 ElementsKindTraits<FAST_HOLEY_SMI_ELEMENTS> > { | |
894 public: | |
895 explicit FastHoleySmiElementsAccessor(const char* name) | |
896 : FastSmiOrObjectElementsAccessor< | |
897 FastHoleySmiElementsAccessor, | |
898 ElementsKindTraits<FAST_HOLEY_SMI_ELEMENTS> >(name) {} | |
899 }; | |
900 | |
901 class FastPackedObjectElementsAccessor | |
902 : public FastSmiOrObjectElementsAccessor< | |
903 FastPackedObjectElementsAccessor, | |
904 ElementsKindTraits<FAST_ELEMENTS> > { | |
905 public: | |
906 explicit FastPackedObjectElementsAccessor(const char* name) | |
907 : FastSmiOrObjectElementsAccessor< | |
908 FastPackedObjectElementsAccessor, | |
909 ElementsKindTraits<FAST_ELEMENTS> >(name) {} | |
910 }; | |
911 | |
912 class FastHoleyObjectElementsAccessor | |
913 : public FastSmiOrObjectElementsAccessor< | |
914 FastHoleyObjectElementsAccessor, | |
915 ElementsKindTraits<FAST_HOLEY_ELEMENTS> > { | |
916 public: | |
917 explicit FastHoleyObjectElementsAccessor(const char* name) | |
918 : FastSmiOrObjectElementsAccessor< | |
919 FastHoleyObjectElementsAccessor, | |
920 ElementsKindTraits<FAST_HOLEY_ELEMENTS> >(name) {} | |
921 }; | |
922 | |
923 template<typename FastElementsAccessorSubclass, | |
924 typename KindTraits> | |
784 class FastDoubleElementsAccessor | 925 class FastDoubleElementsAccessor |
785 : public FastElementsAccessor<FastDoubleElementsAccessor, | 926 : public FastElementsAccessor<FastElementsAccessorSubclass, |
786 ElementsKindTraits<FAST_DOUBLE_ELEMENTS>, | 927 KindTraits, |
787 kDoubleSize> { | 928 kDoubleSize> { |
788 public: | 929 public: |
789 explicit FastDoubleElementsAccessor(const char* name) | 930 explicit FastDoubleElementsAccessor(const char* name) |
790 : FastElementsAccessor<FastDoubleElementsAccessor, | 931 : FastElementsAccessor<FastElementsAccessorSubclass, |
791 ElementsKindTraits<FAST_DOUBLE_ELEMENTS>, | 932 KindTraits, |
792 kDoubleSize>(name) {} | 933 kDoubleSize>(name) {} |
793 | 934 |
794 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | 935 static MaybeObject* SetFastElementsCapacityAndLength( |
Jakob Kummerow
2012/05/13 21:55:27
nit: yet more formatting changes
danno
2012/05/22 11:05:21
Done.
| |
795 uint32_t capacity, | 936 JSObject* obj, |
796 uint32_t length) { | 937 uint32_t capacity, |
797 return obj->SetFastDoubleElementsCapacityAndLength(capacity, length); | 938 uint32_t length) { |
939 return obj->SetFastDoubleElementsCapacityAndLength(capacity, | |
940 length); | |
798 } | 941 } |
799 | 942 |
800 protected: | 943 protected: |
801 friend class ElementsAccessorBase<FastDoubleElementsAccessor, | |
802 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >; | |
803 friend class FastElementsAccessor<FastDoubleElementsAccessor, | |
804 ElementsKindTraits<FAST_DOUBLE_ELEMENTS>, | |
805 kDoubleSize>; | |
806 | |
807 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 944 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
808 uint32_t from_start, | 945 uint32_t from_start, |
809 FixedArrayBase* to, | 946 FixedArrayBase* to, |
810 ElementsKind to_kind, | 947 ElementsKind to_kind, |
811 uint32_t to_start, | 948 uint32_t to_start, |
812 int copy_size) { | 949 int copy_size) { |
813 switch (to_kind) { | 950 switch (to_kind) { |
814 case FAST_SMI_ONLY_ELEMENTS: | 951 case FAST_SMI_ELEMENTS: |
815 case FAST_ELEMENTS: | 952 case FAST_ELEMENTS: |
953 case FAST_HOLEY_SMI_ELEMENTS: | |
954 case FAST_HOLEY_ELEMENTS: | |
816 return CopyDoubleToObjectElements( | 955 return CopyDoubleToObjectElements( |
817 FixedDoubleArray::cast(from), from_start, FixedArray::cast(to), | 956 FixedDoubleArray::cast(from), from_start, FixedArray::cast(to), |
818 to_kind, to_start, copy_size); | 957 to_kind, to_start, copy_size); |
819 case FAST_DOUBLE_ELEMENTS: | 958 case FAST_DOUBLE_ELEMENTS: |
959 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
820 CopyDoubleToDoubleElements(FixedDoubleArray::cast(from), from_start, | 960 CopyDoubleToDoubleElements(FixedDoubleArray::cast(from), from_start, |
821 FixedDoubleArray::cast(to), | 961 FixedDoubleArray::cast(to), |
822 to_start, copy_size); | 962 to_start, copy_size); |
823 return from; | 963 return from; |
824 default: | 964 default: |
825 UNREACHABLE(); | 965 UNREACHABLE(); |
826 } | 966 } |
827 return to->GetHeap()->undefined_value(); | 967 return to->GetHeap()->undefined_value(); |
828 } | 968 } |
829 | |
830 virtual MaybeObject* Delete(JSObject* obj, | |
831 uint32_t key, | |
832 JSReceiver::DeleteMode mode) { | |
833 int length = obj->IsJSArray() | |
834 ? Smi::cast(JSArray::cast(obj)->length())->value() | |
835 : FixedDoubleArray::cast(obj->elements())->length(); | |
836 if (key < static_cast<uint32_t>(length)) { | |
837 FixedDoubleArray::cast(obj->elements())->set_the_hole(key); | |
838 } | |
839 return obj->GetHeap()->true_value(); | |
840 } | |
841 | |
842 static bool HasElementImpl(Object* receiver, | |
843 JSObject* holder, | |
844 uint32_t key, | |
845 FixedDoubleArray* backing_store) { | |
846 return key < static_cast<uint32_t>(backing_store->length()) && | |
847 !backing_store->is_the_hole(key); | |
848 } | |
849 }; | 969 }; |
850 | 970 |
851 | 971 |
972 class FastPackedDoubleElementsAccessor | |
973 : public FastDoubleElementsAccessor< | |
974 FastPackedDoubleElementsAccessor, | |
Jakob Kummerow
2012/05/13 21:55:27
nit: indentation (same for FastHoleyDoubleElements
danno
2012/05/22 11:05:21
Done.
| |
975 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> > { | |
976 public: | |
977 friend class ElementsAccessorBase<FastPackedDoubleElementsAccessor, | |
978 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >; | |
979 explicit FastPackedDoubleElementsAccessor(const char* name) | |
980 : FastDoubleElementsAccessor< | |
981 FastPackedDoubleElementsAccessor, | |
Jakob Kummerow
2012/05/13 21:55:27
again
danno
2012/05/22 11:05:21
Done.
| |
982 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >(name) {} | |
983 }; | |
984 | |
985 class FastHoleyDoubleElementsAccessor | |
986 : public FastDoubleElementsAccessor< | |
987 FastHoleyDoubleElementsAccessor, | |
988 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > { | |
989 public: | |
990 friend class ElementsAccessorBase< | |
991 FastHoleyDoubleElementsAccessor, | |
992 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >; | |
993 explicit FastHoleyDoubleElementsAccessor(const char* name) | |
994 : FastDoubleElementsAccessor< | |
995 FastHoleyDoubleElementsAccessor, | |
996 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {} | |
997 }; | |
998 | |
852 // Super class for all external element arrays. | 999 // Super class for all external element arrays. |
853 template<typename ExternalElementsAccessorSubclass, | 1000 template<typename ExternalElementsAccessorSubclass, |
854 ElementsKind Kind> | 1001 ElementsKind Kind> |
855 class ExternalElementsAccessor | 1002 class ExternalElementsAccessor |
856 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, | 1003 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, |
857 ElementsKindTraits<Kind> > { | 1004 ElementsKindTraits<Kind> > { |
858 public: | 1005 public: |
859 explicit ExternalElementsAccessor(const char* name) | 1006 explicit ExternalElementsAccessor(const char* name) |
860 : ElementsAccessorBase<ExternalElementsAccessorSubclass, | 1007 : ElementsAccessorBase<ExternalElementsAccessorSubclass, |
861 ElementsKindTraits<Kind> >(name) {} | 1008 ElementsKindTraits<Kind> >(name) {} |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1102 return heap->true_value(); | 1249 return heap->true_value(); |
1103 } | 1250 } |
1104 | 1251 |
1105 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 1252 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
1106 uint32_t from_start, | 1253 uint32_t from_start, |
1107 FixedArrayBase* to, | 1254 FixedArrayBase* to, |
1108 ElementsKind to_kind, | 1255 ElementsKind to_kind, |
1109 uint32_t to_start, | 1256 uint32_t to_start, |
1110 int copy_size) { | 1257 int copy_size) { |
1111 switch (to_kind) { | 1258 switch (to_kind) { |
1112 case FAST_SMI_ONLY_ELEMENTS: | 1259 case FAST_SMI_ELEMENTS: |
1113 case FAST_ELEMENTS: | 1260 case FAST_ELEMENTS: |
1261 case FAST_HOLEY_SMI_ELEMENTS: | |
1262 case FAST_HOLEY_ELEMENTS: | |
1114 CopyDictionaryToObjectElements( | 1263 CopyDictionaryToObjectElements( |
1115 SeededNumberDictionary::cast(from), from_start, | 1264 SeededNumberDictionary::cast(from), from_start, |
1116 FixedArray::cast(to), to_kind, to_start, copy_size); | 1265 FixedArray::cast(to), to_kind, to_start, copy_size); |
1117 return from; | 1266 return from; |
1118 case FAST_DOUBLE_ELEMENTS: | 1267 case FAST_DOUBLE_ELEMENTS: |
1268 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
1119 CopyDictionaryToDoubleElements( | 1269 CopyDictionaryToDoubleElements( |
1120 SeededNumberDictionary::cast(from), from_start, | 1270 SeededNumberDictionary::cast(from), from_start, |
1121 FixedDoubleArray::cast(to), to_start, copy_size); | 1271 FixedDoubleArray::cast(to), to_start, copy_size); |
1122 return from; | 1272 return from; |
1123 default: | 1273 default: |
1124 UNREACHABLE(); | 1274 UNREACHABLE(); |
1125 } | 1275 } |
1126 return to->GetHeap()->undefined_value(); | 1276 return to->GetHeap()->undefined_value(); |
1127 } | 1277 } |
1128 | 1278 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1233 if (!probe->IsTheHole()) { | 1383 if (!probe->IsTheHole()) { |
1234 // TODO(kmillikin): We could check if this was the last aliased | 1384 // TODO(kmillikin): We could check if this was the last aliased |
1235 // parameter, and revert to normal elements in that case. That | 1385 // parameter, and revert to normal elements in that case. That |
1236 // would enable GC of the context. | 1386 // would enable GC of the context. |
1237 parameter_map->set_the_hole(key + 2); | 1387 parameter_map->set_the_hole(key + 2); |
1238 } else { | 1388 } else { |
1239 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1389 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1240 if (arguments->IsDictionary()) { | 1390 if (arguments->IsDictionary()) { |
1241 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode); | 1391 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode); |
1242 } else { | 1392 } else { |
1243 return FastObjectElementsAccessor::DeleteCommon(obj, key); | 1393 // It's difficult to access the version of DeleteCommon that is declared |
1394 // in the templatized super class, call the concrete implementation in | |
1395 // the class for the most generalized ElementsKind subclass. | |
1396 return FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, mode); | |
1244 } | 1397 } |
1245 } | 1398 } |
1246 return obj->GetHeap()->true_value(); | 1399 return obj->GetHeap()->true_value(); |
1247 } | 1400 } |
1248 | 1401 |
1249 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, | 1402 static MaybeObject* CopyElementsImpl(FixedArrayBase* from, |
1250 uint32_t from_start, | 1403 uint32_t from_start, |
1251 FixedArrayBase* to, | 1404 FixedArrayBase* to, |
1252 ElementsKind to_kind, | 1405 ElementsKind to_kind, |
1253 uint32_t to_start, | 1406 uint32_t to_start, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1297 } | 1450 } |
1298 }; | 1451 }; |
1299 | 1452 |
1300 | 1453 |
1301 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { | 1454 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { |
1302 switch (array->map()->instance_type()) { | 1455 switch (array->map()->instance_type()) { |
1303 case FIXED_ARRAY_TYPE: | 1456 case FIXED_ARRAY_TYPE: |
1304 if (array->IsDictionary()) { | 1457 if (array->IsDictionary()) { |
1305 return elements_accessors_[DICTIONARY_ELEMENTS]; | 1458 return elements_accessors_[DICTIONARY_ELEMENTS]; |
1306 } else { | 1459 } else { |
1307 return elements_accessors_[FAST_ELEMENTS]; | 1460 return elements_accessors_[FAST_HOLEY_ELEMENTS]; |
1308 } | 1461 } |
1309 case EXTERNAL_BYTE_ARRAY_TYPE: | 1462 case EXTERNAL_BYTE_ARRAY_TYPE: |
1310 return elements_accessors_[EXTERNAL_BYTE_ELEMENTS]; | 1463 return elements_accessors_[EXTERNAL_BYTE_ELEMENTS]; |
1311 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: | 1464 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: |
1312 return elements_accessors_[EXTERNAL_UNSIGNED_BYTE_ELEMENTS]; | 1465 return elements_accessors_[EXTERNAL_UNSIGNED_BYTE_ELEMENTS]; |
1313 case EXTERNAL_SHORT_ARRAY_TYPE: | 1466 case EXTERNAL_SHORT_ARRAY_TYPE: |
1314 return elements_accessors_[EXTERNAL_SHORT_ELEMENTS]; | 1467 return elements_accessors_[EXTERNAL_SHORT_ELEMENTS]; |
1315 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: | 1468 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: |
1316 return elements_accessors_[EXTERNAL_UNSIGNED_SHORT_ELEMENTS]; | 1469 return elements_accessors_[EXTERNAL_UNSIGNED_SHORT_ELEMENTS]; |
1317 case EXTERNAL_INT_ARRAY_TYPE: | 1470 case EXTERNAL_INT_ARRAY_TYPE: |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1408 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; | 1561 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; |
1409 new_backing_store->set(0, length); | 1562 new_backing_store->set(0, length); |
1410 { MaybeObject* result = array->SetContent(new_backing_store); | 1563 { MaybeObject* result = array->SetContent(new_backing_store); |
1411 if (result->IsFailure()) return result; | 1564 if (result->IsFailure()) return result; |
1412 } | 1565 } |
1413 return array; | 1566 return array; |
1414 } | 1567 } |
1415 | 1568 |
1416 | 1569 |
1417 } } // namespace v8::internal | 1570 } } // namespace v8::internal |
OLD | NEW |