Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(465)

Side by Side Diff: src/elements.cc

Issue 8372064: Fix setting array length to be ES5 conform. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments by Daniel Clifford. Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/elements.h ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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* ThrowArrayLengthRangeError(Heap* heap) {
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
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
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
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->HasFastSmiOnlyElements()
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
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
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();
550 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
551 } else {
552 uint32_t new_length = length;
553 uint32_t old_length = static_cast<uint32_t>(array->length()->Number());
554 if (new_length < old_length) {
555 // Find last non-deletable element in range of elements to be
556 // deleted and adjust range accordingly.
557 Heap* heap = array->GetHeap();
558 int capacity = dict->Capacity();
559 for (int i = 0; i < capacity; i++) {
560 Object* key = dict->KeyAt(i);
561 if (key->IsNumber()) {
562 uint32_t number = static_cast<uint32_t>(key->Number());
563 if (new_length <= number && number < old_length) {
564 PropertyDetails details = dict->DetailsAt(i);
565 if (details.IsDontDelete()) new_length = number + 1;
566 }
567 }
568 }
569 if (new_length != length) {
570 MaybeObject* maybe_object = heap->NumberFromUint32(new_length);
571 if (!maybe_object->To(&length_object)) return maybe_object;
572 }
573
574 // Remove elements that should be deleted.
575 int removed_entries = 0;
576 Object* sentinel = heap->null_value();
577 for (int i = 0; i < capacity; i++) {
578 Object* key = dict->KeyAt(i);
579 if (key->IsNumber()) {
580 uint32_t number = static_cast<uint32_t>(key->Number());
581 if (new_length <= number && number < old_length) {
582 dict->SetEntry(i, sentinel, sentinel);
583 removed_entries++;
584 }
585 }
586 }
587
588 // Update the number of elements.
589 dict->ElementsRemoved(removed_entries);
590 }
591 }
592 return length_object;
593 }
594
399 static MaybeObject* DeleteCommon(JSObject* obj, 595 static MaybeObject* DeleteCommon(JSObject* obj,
400 uint32_t key, 596 uint32_t key,
401 JSReceiver::DeleteMode mode) { 597 JSReceiver::DeleteMode mode) {
402 Isolate* isolate = obj->GetIsolate(); 598 Isolate* isolate = obj->GetIsolate();
403 Heap* heap = isolate->heap(); 599 Heap* heap = isolate->heap();
404 FixedArray* backing_store = FixedArray::cast(obj->elements()); 600 FixedArray* backing_store = FixedArray::cast(obj->elements());
405 bool is_arguments = 601 bool is_arguments =
406 (obj->GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS); 602 (obj->GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS);
407 if (is_arguments) { 603 if (is_arguments) {
408 backing_store = FixedArray::cast(backing_store->get(1)); 604 backing_store = FixedArray::cast(backing_store->get(1));
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 } else { 694 } else {
499 // Object is not mapped, defer to the arguments. 695 // Object is not mapped, defer to the arguments.
500 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); 696 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
501 return ElementsAccessor::ForArray(arguments)->Get(arguments, 697 return ElementsAccessor::ForArray(arguments)->Get(arguments,
502 key, 698 key,
503 obj, 699 obj,
504 receiver); 700 receiver);
505 } 701 }
506 } 702 }
507 703
704 static MaybeObject* SetLength(FixedArray* parameter_map,
705 JSObject* obj,
706 Object* length) {
707 // TODO(mstarzinger): This was never implemented but will be used once we
708 // correctly implement [[DefineOwnProperty]] on arrays.
709 UNIMPLEMENTED();
710 return obj;
711 }
712
508 virtual MaybeObject* Delete(JSObject* obj, 713 virtual MaybeObject* Delete(JSObject* obj,
509 uint32_t key 714 uint32_t key,
510 ,
511 JSReceiver::DeleteMode mode) { 715 JSReceiver::DeleteMode mode) {
512 FixedArray* parameter_map = FixedArray::cast(obj->elements()); 716 FixedArray* parameter_map = FixedArray::cast(obj->elements());
513 Object* probe = GetParameterMapArg(parameter_map, key); 717 Object* probe = GetParameterMapArg(parameter_map, key);
514 if (!probe->IsTheHole()) { 718 if (!probe->IsTheHole()) {
515 // TODO(kmillikin): We could check if this was the last aliased 719 // TODO(kmillikin): We could check if this was the last aliased
516 // parameter, and revert to normal elements in that case. That 720 // parameter, and revert to normal elements in that case. That
517 // would enable GC of the context. 721 // would enable GC of the context.
518 parameter_map->set_the_hole(key + 2); 722 parameter_map->set_the_hole(key + 2);
519 } else { 723 } else {
520 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); 724 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
521 if (arguments->IsDictionary()) { 725 if (arguments->IsDictionary()) {
522 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode); 726 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode);
523 } else { 727 } else {
524 return FastElementsAccessor::DeleteCommon(obj, key); 728 return FastObjectElementsAccessor::DeleteCommon(obj, key);
525 } 729 }
526 } 730 }
527 return obj->GetHeap()->true_value(); 731 return obj->GetHeap()->true_value();
528 } 732 }
529 733
530 static uint32_t GetCapacity(FixedArray* parameter_map) { 734 static uint32_t GetCapacity(FixedArray* parameter_map) {
531 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); 735 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
532 return Max(static_cast<uint32_t>(parameter_map->length() - 2), 736 return Max(static_cast<uint32_t>(parameter_map->length() - 2),
533 ForArray(arguments)->GetCapacity(arguments)); 737 ForArray(arguments)->GetCapacity(arguments));
534 } 738 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 UNREACHABLE(); 797 UNREACHABLE();
594 return NULL; 798 return NULL;
595 } 799 }
596 } 800 }
597 801
598 802
599 void ElementsAccessor::InitializeOncePerProcess() { 803 void ElementsAccessor::InitializeOncePerProcess() {
600 static struct ConcreteElementsAccessors { 804 static struct ConcreteElementsAccessors {
601 // Use the fast element handler for smi-only arrays. The implementation is 805 // Use the fast element handler for smi-only arrays. The implementation is
602 // currently identical. 806 // currently identical.
603 FastElementsAccessor fast_smi_elements_handler; 807 FastObjectElementsAccessor fast_smi_elements_handler;
604 FastElementsAccessor fast_elements_handler; 808 FastObjectElementsAccessor fast_elements_handler;
605 FastDoubleElementsAccessor fast_double_elements_handler; 809 FastDoubleElementsAccessor fast_double_elements_handler;
606 DictionaryElementsAccessor dictionary_elements_handler; 810 DictionaryElementsAccessor dictionary_elements_handler;
607 NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler; 811 NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler;
608 ExternalByteElementsAccessor byte_elements_handler; 812 ExternalByteElementsAccessor byte_elements_handler;
609 ExternalUnsignedByteElementsAccessor unsigned_byte_elements_handler; 813 ExternalUnsignedByteElementsAccessor unsigned_byte_elements_handler;
610 ExternalShortElementsAccessor short_elements_handler; 814 ExternalShortElementsAccessor short_elements_handler;
611 ExternalUnsignedShortElementsAccessor unsigned_short_elements_handler; 815 ExternalUnsignedShortElementsAccessor unsigned_short_elements_handler;
612 ExternalIntElementsAccessor int_elements_handler; 816 ExternalIntElementsAccessor int_elements_handler;
613 ExternalUnsignedIntElementsAccessor unsigned_int_elements_handler; 817 ExternalUnsignedIntElementsAccessor unsigned_int_elements_handler;
614 ExternalFloatElementsAccessor float_elements_handler; 818 ExternalFloatElementsAccessor float_elements_handler;
(...skipping 18 matching lines...) Expand all
633 &element_accessors.pixel_elements_handler 837 &element_accessors.pixel_elements_handler
634 }; 838 };
635 839
636 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == 840 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) ==
637 kElementsKindCount); 841 kElementsKindCount);
638 842
639 elements_accessors_ = accessor_array; 843 elements_accessors_ = accessor_array;
640 } 844 }
641 845
642 846
847 template <typename ElementsAccessorSubclass, typename BackingStoreClass>
848 MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, BackingStoreClass>::
849 SetLength(BackingStoreClass* backing_store,
850 JSObject* obj,
851 Object* length) {
852 JSArray* array = JSArray::cast(obj);
853
854 // Fast case: The new length fits into a Smi.
855 MaybeObject* maybe_smi_length = length->ToSmi();
856 Object* smi_length = Smi::FromInt(0);
857 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) {
858 const int value = Smi::cast(smi_length)->value();
859 if (value >= 0) {
860 Object* new_length;
861 MaybeObject* result = ElementsAccessorSubclass::
862 SetLengthWithoutNormalize(backing_store, array, smi_length, value);
863 if (!result->ToObject(&new_length)) return result;
864 ASSERT(new_length->IsSmi() || new_length->IsUndefined());
865 if (new_length->IsSmi()) {
866 array->set_length(Smi::cast(new_length));
867 return array;
868 }
869 } else {
870 return ThrowArrayLengthRangeError(array->GetHeap());
871 }
872 }
873
874 // Slow case: The new length does not fit into a Smi or conversion
875 // to slow elements is needed for other reasons.
876 if (length->IsNumber()) {
877 uint32_t value;
878 if (length->ToArrayIndex(&value)) {
879 NumberDictionary* dictionary;
880 MaybeObject* maybe_object = array->NormalizeElements();
881 if (!maybe_object->To(&dictionary)) return maybe_object;
882 Object* new_length;
883 MaybeObject* result = DictionaryElementsAccessor::
884 SetLengthWithoutNormalize(dictionary, array, length, value);
885 if (!result->ToObject(&new_length)) return result;
886 ASSERT(new_length->IsNumber());
887 array->set_length(new_length);
888 return array;
889 } else {
890 return ThrowArrayLengthRangeError(array->GetHeap());
891 }
892 }
893
894 // Fall-back case: The new length is not a number so make the array
895 // size one and set only element to length.
896 FixedArray* new_backing_store;
897 MaybeObject* maybe_obj = array->GetHeap()->AllocateFixedArray(1);
898 if (!maybe_obj->To(&new_backing_store)) return maybe_obj;
899 new_backing_store->set(0, length);
900 array->SetContent(new_backing_store);
901 return array;
902 }
903
904
643 } } // namespace v8::internal 905 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/elements.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698