OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 13 matching lines...) Expand all Loading... | |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #include "objects.h" | 30 #include "objects.h" |
31 #include "elements.h" | 31 #include "elements.h" |
32 #include "utils.h" | 32 #include "utils.h" |
33 | 33 |
34 | |
35 // Each concrete ElementsAccessor can handle exactly one ElementsKind, | |
36 // several abstract ElementsAccessor classes are used to allow sharing | |
37 // common code. | |
38 // | |
39 // Inheritance hierarchy: | |
40 // - ElementsAccessorBase (abstract) | |
41 // - FastElementsAccessor (abstract) | |
42 // - FastObjectElementsAccessor | |
43 // - FastDoubleElementsAccessor | |
44 // - ExternalElementsAccessor (abstract) | |
45 // - ExternalByteElementsAccessor | |
46 // - ExternalUnsignedByteElementsAccessor | |
47 // - ExternalShortElementsAccessor | |
48 // - ExternalUnsignedShortElementsAccessor | |
49 // - ExternalIntElementsAccessor | |
50 // - ExternalUnsignedIntElementsAccessor | |
51 // - ExternalFloatElementsAccessor | |
52 // - ExternalDoubleElementsAccessor | |
53 // - PixelElementsAccessor | |
54 // - DictionaryElementsAccessor | |
55 // - NonStrictArgumentsElementsAccessor | |
56 | |
57 | |
34 namespace v8 { | 58 namespace v8 { |
35 namespace internal { | 59 namespace internal { |
36 | 60 |
37 | 61 |
38 ElementsAccessor** ElementsAccessor::elements_accessors_; | 62 ElementsAccessor** ElementsAccessor::elements_accessors_; |
39 | 63 |
40 | 64 |
41 bool HasKey(FixedArray* array, Object* key) { | 65 static bool HasKey(FixedArray* array, Object* key) { |
42 int len0 = array->length(); | 66 int len0 = array->length(); |
43 for (int i = 0; i < len0; i++) { | 67 for (int i = 0; i < len0; i++) { |
44 Object* element = array->get(i); | 68 Object* element = array->get(i); |
45 if (element->IsSmi() && element == key) return true; | 69 if (element->IsSmi() && element == key) return true; |
46 if (element->IsString() && | 70 if (element->IsString() && |
47 key->IsString() && String::cast(element)->Equals(String::cast(key))) { | 71 key->IsString() && String::cast(element)->Equals(String::cast(key))) { |
48 return true; | 72 return true; |
49 } | 73 } |
50 } | 74 } |
51 return false; | 75 return false; |
52 } | 76 } |
53 | 77 |
54 | 78 |
79 static Failure* ArrayLengthRangeError(Heap* heap) { | |
danno
2011/11/07 19:26:02
Call this ThrowArrayLengthRangeError
Michael Starzinger
2011/11/08 12:00:33
Done.
| |
80 HandleScope scope(heap->isolate()); | |
81 return heap->isolate()->Throw( | |
82 *heap->isolate()->factory()->NewRangeError("invalid_array_length", | |
83 HandleVector<Object>(NULL, 0))); | |
84 } | |
85 | |
86 | |
55 // Base class for element handler implementations. Contains the | 87 // Base class for element handler implementations. Contains the |
56 // the common logic for objects with different ElementsKinds. | 88 // the common logic for objects with different ElementsKinds. |
57 // Subclasses must specialize method for which the element | 89 // Subclasses must specialize method for which the element |
58 // implementation differs from the base class implementation. | 90 // implementation differs from the base class implementation. |
59 // | 91 // |
60 // This class is intended to be used in the following way: | 92 // This class is intended to be used in the following way: |
61 // | 93 // |
62 // class SomeElementsAccessor : | 94 // class SomeElementsAccessor : |
63 // public ElementsAccessorBase<SomeElementsAccessor, | 95 // public ElementsAccessorBase<SomeElementsAccessor, |
64 // BackingStoreClass> { | 96 // BackingStoreClass> { |
(...skipping 19 matching lines...) Expand all Loading... | |
84 static MaybeObject* Get(BackingStoreClass* backing_store, | 116 static MaybeObject* Get(BackingStoreClass* backing_store, |
85 uint32_t key, | 117 uint32_t key, |
86 JSObject* obj, | 118 JSObject* obj, |
87 Object* receiver) { | 119 Object* receiver) { |
88 if (key < ElementsAccessorSubclass::GetCapacity(backing_store)) { | 120 if (key < ElementsAccessorSubclass::GetCapacity(backing_store)) { |
89 return backing_store->get(key); | 121 return backing_store->get(key); |
90 } | 122 } |
91 return backing_store->GetHeap()->the_hole_value(); | 123 return backing_store->GetHeap()->the_hole_value(); |
92 } | 124 } |
93 | 125 |
126 virtual MaybeObject* SetLength(JSObject* obj, | |
127 Object* length) { | |
128 ASSERT(obj->IsJSArray()); | |
129 return ElementsAccessorSubclass::SetLength( | |
130 BackingStoreClass::cast(obj->elements()), obj, length); | |
131 } | |
132 | |
133 static MaybeObject* SetLength(BackingStoreClass* backing_store, | |
134 JSObject* obj, | |
135 Object* length); | |
136 | |
94 virtual MaybeObject* Delete(JSObject* obj, | 137 virtual MaybeObject* Delete(JSObject* obj, |
95 uint32_t key, | 138 uint32_t key, |
96 JSReceiver::DeleteMode mode) = 0; | 139 JSReceiver::DeleteMode mode) = 0; |
97 | 140 |
98 virtual MaybeObject* AddElementsToFixedArray(FixedArrayBase* from, | 141 virtual MaybeObject* AddElementsToFixedArray(FixedArrayBase* from, |
99 FixedArray* to, | 142 FixedArray* to, |
100 JSObject* holder, | 143 JSObject* holder, |
101 Object* receiver) { | 144 Object* receiver) { |
102 int len0 = to->length(); | 145 int len0 = to->length(); |
103 #ifdef DEBUG | 146 #ifdef DEBUG |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
215 uint32_t index) { | 258 uint32_t index) { |
216 return ElementsAccessorSubclass::GetKeyForIndex( | 259 return ElementsAccessorSubclass::GetKeyForIndex( |
217 BackingStoreClass::cast(backing_store), index); | 260 BackingStoreClass::cast(backing_store), index); |
218 } | 261 } |
219 | 262 |
220 private: | 263 private: |
221 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); | 264 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); |
222 }; | 265 }; |
223 | 266 |
224 | 267 |
268 // Super class for all fast element arrays. | |
269 template<typename FastElementsAccessorSubclass, | |
270 typename BackingStore, | |
271 int ElementSize> | |
225 class FastElementsAccessor | 272 class FastElementsAccessor |
226 : public ElementsAccessorBase<FastElementsAccessor, FixedArray> { | 273 : public ElementsAccessorBase<FastElementsAccessorSubclass, BackingStore> { |
274 protected: | |
275 friend class ElementsAccessorBase<FastElementsAccessorSubclass, BackingStore>; | |
276 | |
277 // Adjusts the length of the fast backing store or returns the new length or | |
278 // undefined in case conversion to a slow backing store should be performed. | |
279 static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store, | |
280 JSArray* array, | |
281 Object* length_object, | |
282 uint32_t length) { | |
283 uint32_t old_capacity = backing_store->length(); | |
284 | |
285 // Check whether the backing store should be shrunk. | |
286 if (length <= old_capacity) { | |
287 if (array->HasFastTypeElements()) { | |
288 MaybeObject* maybe_obj = array->EnsureWritableFastElements(); | |
289 if (!maybe_obj->To(&backing_store)) return maybe_obj; | |
290 } | |
291 if (2 * length <= old_capacity) { | |
292 // If more than half the elements won't be used, trim the array. | |
293 if (length == 0) { | |
294 array->initialize_elements(); | |
295 } else { | |
296 backing_store->set_length(length); | |
297 Address filler_start = backing_store->address() + | |
298 BackingStore::OffsetOfElementAt(length); | |
299 int filler_size = (old_capacity - length) * ElementSize; | |
300 array->GetHeap()->CreateFillerObjectAt(filler_start, filler_size); | |
301 } | |
302 } else { | |
303 // Otherwise, fill the unused tail with holes. | |
304 int old_length = FastD2I(array->length()->Number()); | |
305 for (int i = length; i < old_length; i++) { | |
306 backing_store->set_the_hole(i); | |
307 } | |
308 } | |
309 return length_object; | |
310 } | |
311 | |
312 // Check whether the backing store should be expanded. | |
313 uint32_t min = JSObject::NewElementsCapacity(old_capacity); | |
314 uint32_t new_capacity = length > min ? length : min; | |
315 if (!array->ShouldConvertToSlowElements(new_capacity)) { | |
316 MaybeObject* result = FastElementsAccessorSubclass:: | |
317 SetFastElementsCapacityAndLength(array, new_capacity, length); | |
318 if (result->IsFailure()) return result; | |
319 return length_object; | |
320 } | |
321 | |
322 // Request conversion to slow elements. | |
323 return array->GetHeap()->undefined_value(); | |
324 } | |
325 }; | |
326 | |
327 | |
328 class FastObjectElementsAccessor | |
329 : public FastElementsAccessor<FastObjectElementsAccessor, | |
330 FixedArray, | |
331 kPointerSize> { | |
227 public: | 332 public: |
228 static MaybeObject* DeleteCommon(JSObject* obj, | 333 static MaybeObject* DeleteCommon(JSObject* obj, |
229 uint32_t key) { | 334 uint32_t key) { |
230 ASSERT(obj->HasFastElements() || | 335 ASSERT(obj->HasFastElements() || |
231 obj->HasFastSmiOnlyElements() || | 336 obj->HasFastSmiOnlyElements() || |
232 obj->HasFastArgumentsElements()); | 337 obj->HasFastArgumentsElements()); |
233 Heap* heap = obj->GetHeap(); | 338 Heap* heap = obj->GetHeap(); |
234 FixedArray* backing_store = FixedArray::cast(obj->elements()); | 339 FixedArray* backing_store = FixedArray::cast(obj->elements()); |
235 if (backing_store->map() == heap->non_strict_arguments_elements_map()) { | 340 if (backing_store->map() == heap->non_strict_arguments_elements_map()) { |
236 backing_store = FixedArray::cast(backing_store->get(1)); | 341 backing_store = FixedArray::cast(backing_store->get(1)); |
(...skipping 28 matching lines...) Expand all Loading... | |
265 if (4 * num_used <= backing_store->length()) { | 370 if (4 * num_used <= backing_store->length()) { |
266 MaybeObject* result = obj->NormalizeElements(); | 371 MaybeObject* result = obj->NormalizeElements(); |
267 if (result->IsFailure()) return result; | 372 if (result->IsFailure()) return result; |
268 } | 373 } |
269 } | 374 } |
270 } | 375 } |
271 return heap->true_value(); | 376 return heap->true_value(); |
272 } | 377 } |
273 | 378 |
274 protected: | 379 protected: |
380 friend class FastElementsAccessor<FastObjectElementsAccessor, | |
381 FixedArray, | |
382 kPointerSize>; | |
383 | |
384 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | |
385 uint32_t capacity, | |
386 uint32_t length) { | |
387 JSObject::SetFastElementsCapacityMode set_capacity_mode = | |
388 obj->GetElementsKind() == FAST_SMI_ONLY_ELEMENTS | |
danno
2011/11/07 19:26:02
Use obj->HasFastSmiOnlyElements()
Michael Starzinger
2011/11/08 12:00:33
Done.
| |
389 ? JSObject::kAllowSmiOnlyElements | |
390 : JSObject::kDontAllowSmiOnlyElements; | |
391 return obj->SetFastElementsCapacityAndLength(capacity, | |
392 length, | |
393 set_capacity_mode); | |
394 } | |
395 | |
275 virtual MaybeObject* Delete(JSObject* obj, | 396 virtual MaybeObject* Delete(JSObject* obj, |
276 uint32_t key, | 397 uint32_t key, |
277 JSReceiver::DeleteMode mode) { | 398 JSReceiver::DeleteMode mode) { |
278 return DeleteCommon(obj, key); | 399 return DeleteCommon(obj, key); |
279 } | 400 } |
280 }; | 401 }; |
281 | 402 |
282 | 403 |
283 class FastDoubleElementsAccessor | 404 class FastDoubleElementsAccessor |
284 : public ElementsAccessorBase<FastDoubleElementsAccessor, | 405 : public FastElementsAccessor<FastDoubleElementsAccessor, |
285 FixedDoubleArray> { | 406 FixedDoubleArray, |
407 kDoubleSize> { | |
286 protected: | 408 protected: |
287 friend class ElementsAccessorBase<FastDoubleElementsAccessor, | 409 friend class ElementsAccessorBase<FastDoubleElementsAccessor, |
288 FixedDoubleArray>; | 410 FixedDoubleArray>; |
411 friend class FastElementsAccessor<FastDoubleElementsAccessor, | |
412 FixedDoubleArray, | |
413 kDoubleSize>; | |
414 | |
415 static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj, | |
416 uint32_t capacity, | |
417 uint32_t length) { | |
418 return obj->SetFastDoubleElementsCapacityAndLength(capacity, length); | |
419 } | |
289 | 420 |
290 virtual MaybeObject* Delete(JSObject* obj, | 421 virtual MaybeObject* Delete(JSObject* obj, |
291 uint32_t key, | 422 uint32_t key, |
292 JSReceiver::DeleteMode mode) { | 423 JSReceiver::DeleteMode mode) { |
293 int length = obj->IsJSArray() | 424 int length = obj->IsJSArray() |
294 ? Smi::cast(JSArray::cast(obj)->length())->value() | 425 ? Smi::cast(JSArray::cast(obj)->length())->value() |
295 : FixedDoubleArray::cast(obj->elements())->length(); | 426 : FixedDoubleArray::cast(obj->elements())->length(); |
296 if (key < static_cast<uint32_t>(length)) { | 427 if (key < static_cast<uint32_t>(length)) { |
297 FixedDoubleArray::cast(obj->elements())->set_the_hole(key); | 428 FixedDoubleArray::cast(obj->elements())->set_the_hole(key); |
298 } | 429 } |
(...skipping 23 matching lines...) Expand all Loading... | |
322 uint32_t key, | 453 uint32_t key, |
323 JSObject* obj, | 454 JSObject* obj, |
324 Object* receiver) { | 455 Object* receiver) { |
325 if (key < ExternalElementsAccessorSubclass::GetCapacity(backing_store)) { | 456 if (key < ExternalElementsAccessorSubclass::GetCapacity(backing_store)) { |
326 return backing_store->get(key); | 457 return backing_store->get(key); |
327 } else { | 458 } else { |
328 return backing_store->GetHeap()->undefined_value(); | 459 return backing_store->GetHeap()->undefined_value(); |
329 } | 460 } |
330 } | 461 } |
331 | 462 |
463 static MaybeObject* SetLength(ExternalArray* backing_store, | |
464 JSObject* obj, | |
465 Object* length) { | |
466 // External arrays do not support changing their length. | |
467 UNREACHABLE(); | |
468 return obj; | |
469 } | |
470 | |
332 virtual MaybeObject* Delete(JSObject* obj, | 471 virtual MaybeObject* Delete(JSObject* obj, |
333 uint32_t key, | 472 uint32_t key, |
334 JSReceiver::DeleteMode mode) { | 473 JSReceiver::DeleteMode mode) { |
335 // External arrays always ignore deletes. | 474 // External arrays always ignore deletes. |
336 return obj->GetHeap()->true_value(); | 475 return obj->GetHeap()->true_value(); |
337 } | 476 } |
338 }; | 477 }; |
339 | 478 |
340 | 479 |
341 class ExternalByteElementsAccessor | 480 class ExternalByteElementsAccessor |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
389 class PixelElementsAccessor | 528 class PixelElementsAccessor |
390 : public ExternalElementsAccessor<PixelElementsAccessor, | 529 : public ExternalElementsAccessor<PixelElementsAccessor, |
391 ExternalPixelArray> { | 530 ExternalPixelArray> { |
392 }; | 531 }; |
393 | 532 |
394 | 533 |
395 class DictionaryElementsAccessor | 534 class DictionaryElementsAccessor |
396 : public ElementsAccessorBase<DictionaryElementsAccessor, | 535 : public ElementsAccessorBase<DictionaryElementsAccessor, |
397 NumberDictionary> { | 536 NumberDictionary> { |
398 public: | 537 public: |
538 // Adjusts the length of the dictionary backing store and returns the new | |
539 // length according to ES5 section 15.4.5.2 behavior. | |
540 static MaybeObject* SetLengthWithoutNormalize(NumberDictionary* dict, | |
541 JSArray* array, | |
542 Object* length_object, | |
543 uint32_t length) { | |
544 if (length == 0) { | |
545 // If the length of a slow array is reset to zero, we clear | |
546 // the array and flush backing storage. This has the added | |
547 // benefit that the array returns to fast mode. | |
548 Object* obj; | |
549 { MaybeObject* maybe_obj = array->ResetElements(); | |
danno
2011/11/07 19:26:02
This weird formatting is an artifact of an automat
Michael Starzinger
2011/11/08 12:00:33
Done.
| |
550 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
551 } | |
552 } else { | |
553 uint32_t new_length = length; | |
554 uint32_t old_length = static_cast<uint32_t>(array->length()->Number()); | |
555 if (new_length < old_length) { | |
556 // Find last non-deletable element in range of elements to be | |
557 // deleted and adjust range accordingly. | |
558 Heap* heap = array->GetHeap(); | |
559 int capacity = dict->Capacity(); | |
560 for (int i = 0; i < capacity; i++) { | |
561 Object* key = dict->KeyAt(i); | |
562 if (key->IsNumber()) { | |
563 uint32_t number = static_cast<uint32_t>(key->Number()); | |
564 if (new_length <= number && number < old_length) { | |
565 PropertyDetails details = dict->DetailsAt(i); | |
566 if (details.IsDontDelete()) new_length = number + 1; | |
567 } | |
568 } | |
569 } | |
570 if (new_length != length) { | |
571 MaybeObject* maybe_object = heap->NumberFromUint32(new_length); | |
572 if (!maybe_object->To(&length_object)) return maybe_object; | |
573 } | |
574 | |
575 // Remove elements that should be deleted. | |
576 int removed_entries = 0; | |
577 Object* sentinel = heap->null_value(); | |
578 for (int i = 0; i < capacity; i++) { | |
579 Object* key = dict->KeyAt(i); | |
580 if (key->IsNumber()) { | |
581 uint32_t number = static_cast<uint32_t>(key->Number()); | |
582 if (new_length <= number && number < old_length) { | |
583 dict->SetEntry(i, sentinel, sentinel); | |
584 removed_entries++; | |
585 } | |
586 } | |
587 } | |
588 | |
589 // Update the number of elements. | |
590 dict->ElementsRemoved(removed_entries); | |
591 } | |
592 } | |
593 return length_object; | |
594 } | |
595 | |
399 static MaybeObject* DeleteCommon(JSObject* obj, | 596 static MaybeObject* DeleteCommon(JSObject* obj, |
400 uint32_t key, | 597 uint32_t key, |
401 JSReceiver::DeleteMode mode) { | 598 JSReceiver::DeleteMode mode) { |
402 Isolate* isolate = obj->GetIsolate(); | 599 Isolate* isolate = obj->GetIsolate(); |
403 Heap* heap = isolate->heap(); | 600 Heap* heap = isolate->heap(); |
404 FixedArray* backing_store = FixedArray::cast(obj->elements()); | 601 FixedArray* backing_store = FixedArray::cast(obj->elements()); |
405 bool is_arguments = | 602 bool is_arguments = |
406 (obj->GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS); | 603 (obj->GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS); |
407 if (is_arguments) { | 604 if (is_arguments) { |
408 backing_store = FixedArray::cast(backing_store->get(1)); | 605 backing_store = FixedArray::cast(backing_store->get(1)); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
498 } else { | 695 } else { |
499 // Object is not mapped, defer to the arguments. | 696 // Object is not mapped, defer to the arguments. |
500 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 697 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
501 return ElementsAccessor::ForArray(arguments)->Get(arguments, | 698 return ElementsAccessor::ForArray(arguments)->Get(arguments, |
502 key, | 699 key, |
503 obj, | 700 obj, |
504 receiver); | 701 receiver); |
505 } | 702 } |
506 } | 703 } |
507 | 704 |
705 static MaybeObject* SetLength(FixedArray* parameter_map, | |
706 JSObject* obj, | |
707 Object* length) { | |
708 // TODO(mstarzinger): This was never implemented but will be used once we | |
709 // correctly implement [[DefineOwnProperty]] on arrays. | |
710 UNIMPLEMENTED(); | |
711 return obj; | |
712 } | |
713 | |
508 virtual MaybeObject* Delete(JSObject* obj, | 714 virtual MaybeObject* Delete(JSObject* obj, |
509 uint32_t key | 715 uint32_t key, |
510 , | |
511 JSReceiver::DeleteMode mode) { | 716 JSReceiver::DeleteMode mode) { |
512 FixedArray* parameter_map = FixedArray::cast(obj->elements()); | 717 FixedArray* parameter_map = FixedArray::cast(obj->elements()); |
513 Object* probe = GetParameterMapArg(parameter_map, key); | 718 Object* probe = GetParameterMapArg(parameter_map, key); |
514 if (!probe->IsTheHole()) { | 719 if (!probe->IsTheHole()) { |
515 // TODO(kmillikin): We could check if this was the last aliased | 720 // TODO(kmillikin): We could check if this was the last aliased |
516 // parameter, and revert to normal elements in that case. That | 721 // parameter, and revert to normal elements in that case. That |
517 // would enable GC of the context. | 722 // would enable GC of the context. |
518 parameter_map->set_the_hole(key + 2); | 723 parameter_map->set_the_hole(key + 2); |
519 } else { | 724 } else { |
520 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 725 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
521 if (arguments->IsDictionary()) { | 726 if (arguments->IsDictionary()) { |
522 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode); | 727 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode); |
523 } else { | 728 } else { |
524 return FastElementsAccessor::DeleteCommon(obj, key); | 729 return FastObjectElementsAccessor::DeleteCommon(obj, key); |
525 } | 730 } |
526 } | 731 } |
527 return obj->GetHeap()->true_value(); | 732 return obj->GetHeap()->true_value(); |
528 } | 733 } |
529 | 734 |
530 static uint32_t GetCapacity(FixedArray* parameter_map) { | 735 static uint32_t GetCapacity(FixedArray* parameter_map) { |
531 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 736 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
532 return Max(static_cast<uint32_t>(parameter_map->length() - 2), | 737 return Max(static_cast<uint32_t>(parameter_map->length() - 2), |
533 ForArray(arguments)->GetCapacity(arguments)); | 738 ForArray(arguments)->GetCapacity(arguments)); |
534 } | 739 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
593 UNREACHABLE(); | 798 UNREACHABLE(); |
594 return NULL; | 799 return NULL; |
595 } | 800 } |
596 } | 801 } |
597 | 802 |
598 | 803 |
599 void ElementsAccessor::InitializeOncePerProcess() { | 804 void ElementsAccessor::InitializeOncePerProcess() { |
600 static struct ConcreteElementsAccessors { | 805 static struct ConcreteElementsAccessors { |
601 // Use the fast element handler for smi-only arrays. The implementation is | 806 // Use the fast element handler for smi-only arrays. The implementation is |
602 // currently identical. | 807 // currently identical. |
603 FastElementsAccessor fast_smi_elements_handler; | 808 FastObjectElementsAccessor fast_smi_elements_handler; |
604 FastElementsAccessor fast_elements_handler; | 809 FastObjectElementsAccessor fast_elements_handler; |
605 FastDoubleElementsAccessor fast_double_elements_handler; | 810 FastDoubleElementsAccessor fast_double_elements_handler; |
606 DictionaryElementsAccessor dictionary_elements_handler; | 811 DictionaryElementsAccessor dictionary_elements_handler; |
607 NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler; | 812 NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler; |
608 ExternalByteElementsAccessor byte_elements_handler; | 813 ExternalByteElementsAccessor byte_elements_handler; |
609 ExternalUnsignedByteElementsAccessor unsigned_byte_elements_handler; | 814 ExternalUnsignedByteElementsAccessor unsigned_byte_elements_handler; |
610 ExternalShortElementsAccessor short_elements_handler; | 815 ExternalShortElementsAccessor short_elements_handler; |
611 ExternalUnsignedShortElementsAccessor unsigned_short_elements_handler; | 816 ExternalUnsignedShortElementsAccessor unsigned_short_elements_handler; |
612 ExternalIntElementsAccessor int_elements_handler; | 817 ExternalIntElementsAccessor int_elements_handler; |
613 ExternalUnsignedIntElementsAccessor unsigned_int_elements_handler; | 818 ExternalUnsignedIntElementsAccessor unsigned_int_elements_handler; |
614 ExternalFloatElementsAccessor float_elements_handler; | 819 ExternalFloatElementsAccessor float_elements_handler; |
(...skipping 18 matching lines...) Expand all Loading... | |
633 &element_accessors.pixel_elements_handler | 838 &element_accessors.pixel_elements_handler |
634 }; | 839 }; |
635 | 840 |
636 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == | 841 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == |
637 kElementsKindCount); | 842 kElementsKindCount); |
638 | 843 |
639 elements_accessors_ = accessor_array; | 844 elements_accessors_ = accessor_array; |
640 } | 845 } |
641 | 846 |
642 | 847 |
848 template <typename ElementsAccessorSubclass, typename BackingStoreClass> | |
849 MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, BackingStoreClass>:: | |
850 SetLength(BackingStoreClass* backing_store, | |
851 JSObject* obj, | |
852 Object* length) { | |
853 JSArray* array = JSArray::cast(obj); | |
854 | |
855 // Fast case: The new length fits into a Smi. | |
856 MaybeObject* maybe_smi_length = length->ToSmi(); | |
857 Object* smi_length = Smi::FromInt(0); | |
858 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { | |
859 const int value = Smi::cast(smi_length)->value(); | |
860 if (value >= 0) { | |
861 Object* new_length; | |
862 MaybeObject* result = ElementsAccessorSubclass:: | |
863 SetLengthWithoutNormalize(backing_store, array, smi_length, value); | |
864 if (!result->ToObject(&new_length)) return result; | |
865 ASSERT(new_length->IsSmi() || new_length->IsUndefined()); | |
866 if (new_length->IsSmi()) { | |
867 array->set_length(Smi::cast(new_length)); | |
868 return array; | |
869 } | |
870 } else { | |
871 return ArrayLengthRangeError(array->GetHeap()); | |
872 } | |
873 } | |
874 | |
875 // Slow case: The new length does not fit into a Smi or conversion | |
876 // to slow elements is needed for other reasons. | |
877 if (length->IsNumber()) { | |
878 uint32_t value; | |
879 if (length->ToArrayIndex(&value)) { | |
880 NumberDictionary* dictionary; | |
881 { MaybeObject* maybe_object = array->NormalizeElements(); | |
882 if (!maybe_object->To(&dictionary)) return maybe_object; | |
danno
2011/11/07 19:26:02
remove extra scope
Michael Starzinger
2011/11/08 12:00:33
Done.
| |
883 } | |
884 Object* new_length; | |
885 MaybeObject* result = DictionaryElementsAccessor:: | |
886 SetLengthWithoutNormalize(dictionary, array, length, value); | |
887 if (!result->ToObject(&new_length)) return result; | |
888 ASSERT(new_length->IsNumber()); | |
889 array->set_length(new_length); | |
890 return array; | |
891 } else { | |
892 return ArrayLengthRangeError(array->GetHeap()); | |
893 } | |
894 } | |
895 | |
896 // Fall-back case: The new length is not a number so make the array | |
897 // size one and set only element to length. | |
898 FixedArray* new_backing_store; | |
899 { MaybeObject* maybe_obj = array->GetHeap()->AllocateFixedArray(1); | |
danno
2011/11/07 19:26:02
prune extra scope
Michael Starzinger
2011/11/08 12:00:33
Done.
| |
900 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; | |
901 } | |
902 new_backing_store->set(0, length); | |
903 | |
904 { MaybeObject* maybe_obj = array->EnsureCanContainElements(&length, 1); | |
danno
2011/11/07 19:26:02
prune extra scope
Michael Starzinger
2011/11/08 12:00:33
Done.
| |
905 if (maybe_obj->IsFailure()) return maybe_obj; | |
906 } | |
907 | |
908 array->set_length(Smi::FromInt(1)); | |
909 array->set_elements(new_backing_store); | |
danno
2011/11/07 19:26:02
Consider using array->SetContent to simplify the p
Michael Starzinger
2011/11/08 12:00:33
Done.
| |
910 return array; | |
911 } | |
912 | |
913 | |
643 } } // namespace v8::internal | 914 } } // namespace v8::internal |
OLD | NEW |