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

Side by Side Diff: src/objects.cc

Issue 1197133003: Move SetFastElementsCapacity into GrowCapacityAndConvert (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 6 months 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
« no previous file with comments | « src/objects.h ('k') | src/runtime/runtime-array.cc » ('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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <iomanip> 5 #include <iomanip>
6 #include <sstream> 6 #include <sstream>
7 7
8 #include "src/v8.h" 8 #include "src/v8.h"
9 9
10 #include "src/accessors.h" 10 #include "src/accessors.h"
(...skipping 3371 matching lines...) Expand 10 before | Expand all | Expand 10 after
3382 array->HasFixedTypedArrayElements())) { 3382 array->HasFixedTypedArrayElements())) {
3383 CheckArrayAbuse(array, "typed elements write", it->index(), true); 3383 CheckArrayAbuse(array, "typed elements write", it->index(), true);
3384 } 3384 }
3385 3385
3386 if (FLAG_trace_js_array_abuse && !array->HasExternalArrayElements() && 3386 if (FLAG_trace_js_array_abuse && !array->HasExternalArrayElements() &&
3387 !array->HasFixedTypedArrayElements()) { 3387 !array->HasFixedTypedArrayElements()) {
3388 CheckArrayAbuse(array, "elements write", it->index(), false); 3388 CheckArrayAbuse(array, "elements write", it->index(), false);
3389 } 3389 }
3390 } 3390 }
3391 3391
3392 return JSObject::AddDataElement(receiver, it->index(), value, attributes); 3392 MaybeHandle<Object> result =
3393 JSObject::AddDataElement(receiver, it->index(), value, attributes);
3394 JSObject::ValidateElements(receiver);
3395 return result;
3393 } else { 3396 } else {
3394 // Migrate to the most up-to-date map that will be able to store |value| 3397 // Migrate to the most up-to-date map that will be able to store |value|
3395 // under it->name() with |attributes|. 3398 // under it->name() with |attributes|.
3396 it->PrepareTransitionToDataProperty(value, attributes, store_mode); 3399 it->PrepareTransitionToDataProperty(value, attributes, store_mode);
3397 DCHECK_EQ(LookupIterator::TRANSITION, it->state()); 3400 DCHECK_EQ(LookupIterator::TRANSITION, it->state());
3398 it->ApplyTransitionToDataProperty(); 3401 it->ApplyTransitionToDataProperty();
3399 3402
3400 // TODO(verwaest): Encapsulate dictionary handling better. 3403 // TODO(verwaest): Encapsulate dictionary handling better.
3401 if (receiver->map()->is_dictionary_map()) { 3404 if (receiver->map()->is_dictionary_map()) {
3402 // TODO(verwaest): Probably should ensure this is done beforehand. 3405 // TODO(verwaest): Probably should ensure this is done beforehand.
(...skipping 8392 matching lines...) Expand 10 before | Expand all | Expand 10 after
11795 11798
11796 os << "RelocInfo (size = " << relocation_size() << ")\n"; 11799 os << "RelocInfo (size = " << relocation_size() << ")\n";
11797 for (RelocIterator it(this); !it.done(); it.next()) { 11800 for (RelocIterator it(this); !it.done(); it.next()) {
11798 it.rinfo()->Print(GetIsolate(), os); 11801 it.rinfo()->Print(GetIsolate(), os);
11799 } 11802 }
11800 os << "\n"; 11803 os << "\n";
11801 } 11804 }
11802 #endif // ENABLE_DISASSEMBLER 11805 #endif // ENABLE_DISASSEMBLER
11803 11806
11804 11807
11805 Handle<FixedArray> JSObject::SetFastElementsCapacity(
11806 Handle<JSObject> object, int capacity,
11807 SetFastElementsCapacitySmiMode smi_mode) {
11808 // We should never end in here with a pixel or external array.
11809 DCHECK(!object->HasExternalArrayElements());
11810
11811 // Allocate a new fast elements backing store.
11812 Isolate* isolate = object->GetIsolate();
11813 Handle<FixedArray> new_elements =
11814 isolate->factory()->NewUninitializedFixedArray(capacity);
11815
11816 isolate->UpdateArrayProtectorOnSetLength(object);
11817
11818 ElementsKind elements_kind = object->GetElementsKind();
11819 ElementsKind new_elements_kind;
11820 // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
11821 // or if it's allowed and the old elements array contained only SMIs.
11822 bool has_fast_smi_elements =
11823 (smi_mode == kForceSmiElements) ||
11824 ((smi_mode == kAllowSmiElements) && object->HasFastSmiElements());
11825 if (has_fast_smi_elements) {
11826 if (IsHoleyElementsKind(elements_kind)) {
11827 new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
11828 } else {
11829 new_elements_kind = FAST_SMI_ELEMENTS;
11830 }
11831 } else {
11832 if (IsHoleyElementsKind(elements_kind)) {
11833 new_elements_kind = FAST_HOLEY_ELEMENTS;
11834 } else {
11835 new_elements_kind = FAST_ELEMENTS;
11836 }
11837 }
11838 Handle<FixedArrayBase> old_elements(object->elements());
11839 ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind);
11840 accessor->CopyElements(object, new_elements, elements_kind);
11841
11842 if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) {
11843 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(old_elements);
11844 parameter_map->set(1, *new_elements);
11845 } else {
11846 Handle<Map> new_map = (new_elements_kind != elements_kind)
11847 ? GetElementsTransitionMap(object, new_elements_kind)
11848 : handle(object->map());
11849 JSObject::ValidateElements(object);
11850 JSObject::SetMapAndElements(object, new_map, new_elements);
11851
11852 // Transition through the allocation site as well if present.
11853 JSObject::UpdateAllocationSite(object, new_elements_kind);
11854 }
11855
11856 if (FLAG_trace_elements_transitions) {
11857 PrintElementsTransition(stdout, object, elements_kind, old_elements,
11858 object->GetElementsKind(), new_elements);
11859 }
11860
11861 return new_elements;
11862 }
11863
11864
11865 Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength(
11866 Handle<JSObject> object, int capacity, int length,
11867 SetFastElementsCapacitySmiMode smi_mode) {
11868 Handle<FixedArray> new_elements =
11869 SetFastElementsCapacity(object, capacity, smi_mode);
11870 if (object->IsJSArray()) {
11871 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11872 }
11873 return new_elements;
11874 }
11875
11876
11877 void JSObject::SetFastDoubleElementsCapacityAndLength(Handle<JSObject> object,
11878 int capacity,
11879 int length) {
11880 ElementsAccessor* accessor = ElementsAccessor::ForKind(FAST_DOUBLE_ELEMENTS);
11881 accessor->GrowCapacityAndConvert(object, capacity);
11882 if (object->IsJSArray()) {
11883 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
11884 }
11885 }
11886
11887
11888 // static 11808 // static
11889 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) { 11809 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
11890 DCHECK(capacity >= 0); 11810 DCHECK(capacity >= 0);
11891 array->GetIsolate()->factory()->NewJSArrayStorage( 11811 array->GetIsolate()->factory()->NewJSArrayStorage(
11892 array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE); 11812 array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
11893 } 11813 }
11894 11814
11895 11815
11896 // Returns false if the passed-in index is marked non-configurable, which will 11816 // Returns false if the passed-in index is marked non-configurable, which will
11897 // cause the truncation operation to halt, and thus no further old values need 11817 // cause the truncation operation to halt, and thus no further old values need
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after
12431 FixedArray* arguments = FixedArray::cast(elements->get(1)); 12351 FixedArray* arguments = FixedArray::cast(elements->get(1));
12432 return arguments->IsDictionary(); 12352 return arguments->IsDictionary();
12433 } 12353 }
12434 12354
12435 12355
12436 void JSObject::AddFastElement(Handle<JSObject> object, uint32_t index, 12356 void JSObject::AddFastElement(Handle<JSObject> object, uint32_t index,
12437 Handle<Object> value) { 12357 Handle<Object> value) {
12438 DCHECK(object->HasFastSmiOrObjectElements() || 12358 DCHECK(object->HasFastSmiOrObjectElements() ||
12439 object->HasFastArgumentsElements()); 12359 object->HasFastArgumentsElements());
12440 12360
12441 Isolate* isolate = object->GetIsolate();
12442
12443 Handle<FixedArray> backing_store(FixedArray::cast(object->elements())); 12361 Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
12444 if (object->HasSloppyArgumentsElements()) { 12362 if (object->HasSloppyArgumentsElements()) {
12445 backing_store = handle(FixedArray::cast(backing_store->get(1))); 12363 backing_store = handle(FixedArray::cast(backing_store->get(1)));
12446 } else { 12364 } else {
12447 // Array optimizations rely on the prototype lookups of Array objects always
12448 // returning undefined. If there is a store to the initial prototype object,
12449 // make sure all of these optimizations are invalidated.
12450 isolate->UpdateArrayProtectorOnSetElement(object);
12451 backing_store = EnsureWritableFastElements(object); 12365 backing_store = EnsureWritableFastElements(object);
12452 } 12366 }
12453 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); 12367 uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12454 12368
12455 uint32_t new_capacity = capacity;
12456 // Check if the length property of this object needs to be updated. 12369 // Check if the length property of this object needs to be updated.
12457 uint32_t array_length = 0; 12370 uint32_t array_length = 0;
12458 bool must_update_array_length = false; 12371 bool must_update_array_length = false;
12459 bool introduces_holes = true; 12372 bool introduces_holes = true;
12460 if (object->IsJSArray()) { 12373 if (object->IsJSArray()) {
12461 CHECK( 12374 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&array_length));
12462 Handle<JSArray>::cast(object)->length()->ToArrayLength(&array_length));
12463 introduces_holes = index > array_length; 12375 introduces_holes = index > array_length;
12464 if (index >= array_length) { 12376 if (index >= array_length) {
12465 must_update_array_length = true; 12377 must_update_array_length = true;
12466 array_length = index + 1; 12378 array_length = index + 1;
12467 } 12379 }
12468 } else { 12380 } else {
12469 introduces_holes = index >= capacity; 12381 introduces_holes = index >= capacity;
12470 } 12382 }
12471 12383
12472 // If the array is growing, and it's not growth by a single element at the 12384 uint32_t new_capacity = capacity;
12473 // end, make sure that the ElementsKind is HOLEY.
12474 if (introduces_holes && !IsFastHoleyElementsKind(object->GetElementsKind())) {
12475 ElementsKind transitioned_kind =
12476 GetHoleyElementsKind(object->GetElementsKind());
12477 TransitionElementsKind(object, transitioned_kind);
12478 }
12479
12480 // Check if the capacity of the backing store needs to be increased, or if 12385 // Check if the capacity of the backing store needs to be increased, or if
12481 // a transition to slow elements is necessary. 12386 // a transition to slow elements is necessary.
12482 if (index >= capacity) { 12387 if (index >= capacity) {
12483 bool convert_to_slow = true; 12388 bool convert_to_slow = true;
12484 if ((index - capacity) < kMaxGap) { 12389 if ((index - capacity) < kMaxGap) {
12485 new_capacity = NewElementsCapacity(index + 1); 12390 new_capacity = NewElementsCapacity(index + 1);
12486 DCHECK(new_capacity > index); 12391 DCHECK_LT(index, new_capacity);
12487 if (!object->ShouldConvertToSlowElements(new_capacity)) { 12392 convert_to_slow = object->ShouldConvertToSlowElements(new_capacity);
12488 convert_to_slow = false;
12489 }
12490 } 12393 }
12491 if (convert_to_slow) { 12394 if (convert_to_slow) {
12492 NormalizeElements(object); 12395 NormalizeElements(object);
12493 AddDictionaryElement(object, index, value, NONE); 12396 AddDictionaryElement(object, index, value, NONE);
12494 return; 12397 return;
12495 } 12398 }
12496 } 12399 }
12497 12400
12498 if (object->HasFastSmiElements() && !value->IsSmi()) { 12401 if (object->HasFastSmiElements() && !value->IsSmi()) {
12499 // Convert to fast double elements if appropriate. 12402 // Convert to fast double elements if appropriate.
12500 if (value->IsNumber()) { 12403 if (value->IsNumber()) {
12501 // Consider fixing the boilerplate as well if we have one. 12404 ElementsKind to_kind =
12502 ElementsKind to_kind = IsHoleyElementsKind(object->GetElementsKind()) 12405 introduces_holes ? FAST_HOLEY_DOUBLE_ELEMENTS : FAST_DOUBLE_ELEMENTS;
12503 ? FAST_HOLEY_DOUBLE_ELEMENTS 12406 ElementsAccessor* accessor = ElementsAccessor::ForKind(to_kind);
12504 : FAST_DOUBLE_ELEMENTS; 12407 accessor->GrowCapacityAndConvert(object, new_capacity);
12505 12408 AddFastDoubleElement(object, index, value);
12506 UpdateAllocationSite(object, to_kind);
12507
12508 SetFastDoubleElementsCapacityAndLength(object, new_capacity,
12509 array_length);
12510 FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12511 JSObject::ValidateElements(object);
12512 return; 12409 return;
12513 } 12410 }
12514 12411
12515 // Change elements kind from Smi-only to generic FAST if necessary. 12412 // Change elements kind from Smi-only to generic FAST if necessary.
12516 ElementsKind kind = object->HasFastHoleyElements() 12413 ElementsKind kind = introduces_holes || object->HasFastHoleyElements()
12517 ? FAST_HOLEY_ELEMENTS 12414 ? FAST_HOLEY_ELEMENTS
12518 : FAST_ELEMENTS; 12415 : FAST_ELEMENTS;
12519 12416
12520 UpdateAllocationSite(object, kind); 12417 UpdateAllocationSite(object, kind);
12521 Handle<Map> new_map = GetElementsTransitionMap(object, kind); 12418 Handle<Map> new_map = GetElementsTransitionMap(object, kind);
12522 JSObject::MigrateToMap(object, new_map); 12419 JSObject::MigrateToMap(object, new_map);
12523 DCHECK(IsFastObjectElementsKind(object->GetElementsKind())); 12420 DCHECK(IsFastObjectElementsKind(object->GetElementsKind()));
12421 } else if (introduces_holes && !object->HasFastHoleyElements()) {
12422 // If the array is growing, and it's not growth by a single element at the
12423 // end, make sure that the ElementsKind is HOLEY.
12424 ElementsKind transitioned_kind =
12425 GetHoleyElementsKind(object->GetElementsKind());
12426 TransitionElementsKind(object, transitioned_kind);
12524 } 12427 }
12525 12428
12526 // Increase backing store capacity if that's been decided previously. 12429 // Increase backing store capacity if that's been decided previously.
12527 // Otherwise, set the new element and length. 12430 if (capacity != new_capacity) {
12528 if (new_capacity == capacity) { 12431 DCHECK(!object->HasFastDoubleElements());
12529 DCHECK(object->elements()->IsFixedArray()); 12432 ElementsAccessor* accessor =
12530 backing_store->set(index, *value); 12433 value->IsSmi() || object->HasSloppyArgumentsElements()
12531 if (must_update_array_length) { 12434 ? object->GetElementsAccessor()
12532 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length)); 12435 : ElementsAccessor::ForKind(FAST_ELEMENTS);
12533 } 12436 accessor->GrowCapacityAndConvert(object, new_capacity);
12534 } else {
12535 SetFastElementsCapacitySmiMode smi_mode =
12536 value->IsSmi() && object->HasFastSmiElements()
12537 ? kAllowSmiElements
12538 : kDontAllowSmiElements;
12539 Handle<FixedArray> new_elements =
12540 SetFastElementsCapacityAndLength(object, new_capacity, array_length,
12541 smi_mode);
12542 new_elements->set(index, *value);
12543 JSObject::ValidateElements(object);
12544 } 12437 }
12438
12439 if (must_update_array_length) {
12440 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
12441 }
12442
12443 FixedArray* elements = FixedArray::cast(object->elements());
12444 if (object->HasSloppyArgumentsElements()) {
12445 elements = FixedArray::cast(elements->get(1));
12446 }
12447 elements->set(index, *value);
12545 } 12448 }
12546 12449
12547 12450
12548 void JSObject::SetDictionaryArgumentsElement(Handle<JSObject> object, 12451 void JSObject::SetDictionaryArgumentsElement(Handle<JSObject> object,
12549 uint32_t index, 12452 uint32_t index,
12550 Handle<Object> value, 12453 Handle<Object> value,
12551 PropertyAttributes attributes) { 12454 PropertyAttributes attributes) {
12552 // TODO(verwaest): Handle with the elements accessor. 12455 // TODO(verwaest): Handle with the elements accessor.
12553 Isolate* isolate = object->GetIsolate(); 12456 Isolate* isolate = object->GetIsolate();
12554 12457
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
12694 12597
12695 // Attempt to put this object back in fast case. 12598 // Attempt to put this object back in fast case.
12696 if (object->ShouldConvertToFastElements()) { 12599 if (object->ShouldConvertToFastElements()) {
12697 uint32_t new_length = 0; 12600 uint32_t new_length = 0;
12698 if (object->IsJSArray()) { 12601 if (object->IsJSArray()) {
12699 CHECK( 12602 CHECK(
12700 Handle<JSArray>::cast(object)->length()->ToArrayLength(&new_length)); 12603 Handle<JSArray>::cast(object)->length()->ToArrayLength(&new_length));
12701 } else { 12604 } else {
12702 new_length = dictionary->max_number_key() + 1; 12605 new_length = dictionary->max_number_key() + 1;
12703 } 12606 }
12704 bool has_smi_only_elements = false; 12607 ElementsKind to_kind = object->BestFittingFastElementsKind();
12705 bool should_convert_to_fast_double_elements = 12608 ElementsAccessor* accessor = ElementsAccessor::ForKind(to_kind);
12706 object->ShouldConvertToFastDoubleElements(&has_smi_only_elements); 12609 accessor->GrowCapacityAndConvert(object, new_length);
12707 SetFastElementsCapacitySmiMode smi_mode =
12708 has_smi_only_elements ? kForceSmiElements : kAllowSmiElements;
12709
12710 if (should_convert_to_fast_double_elements) {
12711 SetFastDoubleElementsCapacityAndLength(object, new_length, new_length);
12712 } else {
12713 SetFastElementsCapacityAndLength(object, new_length, new_length,
12714 smi_mode);
12715 }
12716 JSObject::ValidateElements(object);
12717 #ifdef DEBUG 12610 #ifdef DEBUG
12718 if (FLAG_trace_normalization) { 12611 if (FLAG_trace_normalization) {
12719 OFStream os(stdout); 12612 OFStream os(stdout);
12720 os << "Object elements are fast case again:\n"; 12613 os << "Object elements are fast case again:\n";
12721 object->Print(os); 12614 object->Print(os);
12722 } 12615 }
12723 #endif 12616 #endif
12724 } 12617 }
12725 } 12618 }
12726 12619
12727 12620
12728 void JSObject::AddFastDoubleElement(Handle<JSObject> object, uint32_t index, 12621 void JSObject::AddFastDoubleElement(Handle<JSObject> object, uint32_t index,
12729 Handle<Object> value) { 12622 Handle<Object> value) {
12730 DCHECK(object->HasFastDoubleElements()); 12623 DCHECK(object->HasFastDoubleElements());
12731 12624
12732 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements())); 12625 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements()));
12733 uint32_t elms_length = static_cast<uint32_t>(base_elms->length()); 12626 uint32_t capacity = static_cast<uint32_t>(base_elms->length());
12734 uint32_t length = elms_length;
12735 12627
12628 // Check if the length property of this object needs to be updated.
12629 uint32_t array_length = 0;
12630 bool must_update_array_length = false;
12736 bool introduces_holes = true; 12631 bool introduces_holes = true;
12737 if (object->IsJSArray()) { 12632 if (object->IsJSArray()) {
12738 // In case of JSArray, the length does not equal the capacity. 12633 // In case of JSArray, the length does not equal the capacity.
12739 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(&length)); 12634 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&array_length));
12740 introduces_holes = index > length; 12635 introduces_holes = index > array_length;
12636 if (index >= array_length) {
12637 must_update_array_length = true;
12638 array_length = index + 1;
12639 }
12741 } else { 12640 } else {
12742 introduces_holes = index >= elms_length; 12641 introduces_holes = index >= capacity;
12642 }
12643
12644 uint32_t new_capacity = capacity;
12645 // Check if the capacity of the backing store needs to be increased, or if
12646 // a transition to slow elements is necessary.
12647 if (index >= capacity) {
12648 bool convert_to_slow = true;
12649 if ((index - capacity) < kMaxGap) {
12650 new_capacity = NewElementsCapacity(index + 1);
12651 DCHECK_LT(index, new_capacity);
12652 convert_to_slow = object->ShouldConvertToSlowElements(new_capacity);
12653 }
12654 if (convert_to_slow) {
12655 NormalizeElements(object);
12656 AddDictionaryElement(object, index, value, NONE);
12657 return;
12658 }
12743 } 12659 }
12744 12660
12745 // If the value object is not a heap number, switch to fast elements and try 12661 // If the value object is not a heap number, switch to fast elements and try
12746 // again. 12662 // again.
12747 if (!value->IsNumber()) { 12663 if (!value->IsNumber()) {
12748 SetFastElementsCapacityAndLength(object, elms_length, length, 12664 ElementsKind to_kind =
12749 kDontAllowSmiElements); 12665 introduces_holes ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
12750 AddFastElement(object, index, value); 12666 ElementsAccessor* accessor = ElementsAccessor::ForKind(to_kind);
12751 return; 12667 accessor->GrowCapacityAndConvert(object, new_capacity);
12668 return AddFastElement(object, index, value);
12752 } 12669 }
12753 12670
12754 // If the array is growing, and it's not growth by a single element at the 12671 // If the array is growing, and it's not growth by a single element at the
12755 // end, make sure that the ElementsKind is HOLEY. 12672 // end, make sure that the ElementsKind is HOLEY.
12756 if (introduces_holes && !IsFastHoleyElementsKind(object->GetElementsKind())) { 12673 if (introduces_holes && !object->HasFastHoleyElements()) {
12757 ElementsKind transitioned_kind = FAST_HOLEY_DOUBLE_ELEMENTS; 12674 ElementsKind transitioned_kind =
12675 GetHoleyElementsKind(object->GetElementsKind());
12758 TransitionElementsKind(object, transitioned_kind); 12676 TransitionElementsKind(object, transitioned_kind);
12759 } 12677 }
12760 12678
12761 // Check whether there is extra space in the fixed array. 12679 // Increase backing store capacity if that's been decided previously.
12762 if (index < elms_length) { 12680 if (capacity != new_capacity) {
12763 Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements())); 12681 ElementsAccessor* accessor = object->GetElementsAccessor();
12764 elms->set(index, value->Number()); 12682 accessor->GrowCapacityAndConvert(object, new_capacity);
12765 if (object->IsJSArray()) {
12766 // Update the length of the array if needed.
12767 uint32_t array_length = 0;
12768 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(
12769 &array_length));
12770 if (index >= array_length) {
12771 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1));
12772 }
12773 }
12774 return;
12775 } 12683 }
12776 12684
12777 // Allow gap in fast case. 12685 if (must_update_array_length) {
12778 if ((index - elms_length) < kMaxGap) { 12686 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
12779 // Try allocating extra space.
12780 int new_capacity = NewElementsCapacity(index+1);
12781 if (!object->ShouldConvertToSlowElements(new_capacity)) {
12782 DCHECK(static_cast<uint32_t>(new_capacity) > index);
12783 SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1);
12784 FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12785 JSObject::ValidateElements(object);
12786 return;
12787 }
12788 } 12687 }
12789 12688
12790 // Otherwise default to slow case. 12689 FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12791 DCHECK(object->HasFastDoubleElements());
12792 DCHECK(object->map()->has_fast_double_elements());
12793 DCHECK(object->elements()->IsFixedDoubleArray() ||
12794 object->elements()->length() == 0);
12795
12796 NormalizeElements(object);
12797 DCHECK(object->HasDictionaryElements());
12798 AddDictionaryElement(object, index, value, NONE);
12799 } 12690 }
12800 12691
12801 12692
12802 // static 12693 // static
12803 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, 12694 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
12804 uint32_t index, Handle<Object> value, 12695 uint32_t index, Handle<Object> value,
12805 LanguageMode language_mode) { 12696 LanguageMode language_mode) {
12806 Isolate* isolate = object->GetIsolate(); 12697 Isolate* isolate = object->GetIsolate();
12807 LookupIterator it(isolate, object, index); 12698 LookupIterator it(isolate, object, index);
12808 return SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED); 12699 return SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED);
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
13016 12907
13017 // Walk through to the Allocation Site 12908 // Walk through to the Allocation Site
13018 site = handle(memento->GetAllocationSite()); 12909 site = handle(memento->GetAllocationSite());
13019 } 12910 }
13020 AllocationSite::DigestTransitionFeedback(site, to_kind); 12911 AllocationSite::DigestTransitionFeedback(site, to_kind);
13021 } 12912 }
13022 12913
13023 12914
13024 void JSObject::TransitionElementsKind(Handle<JSObject> object, 12915 void JSObject::TransitionElementsKind(Handle<JSObject> object,
13025 ElementsKind to_kind) { 12916 ElementsKind to_kind) {
13026 ElementsKind from_kind = object->map()->elements_kind(); 12917 ElementsKind from_kind = object->GetElementsKind();
13027 12918
13028 if (IsFastHoleyElementsKind(from_kind)) { 12919 if (IsFastHoleyElementsKind(from_kind)) {
13029 to_kind = GetHoleyElementsKind(to_kind); 12920 to_kind = GetHoleyElementsKind(to_kind);
13030 } 12921 }
13031 12922
13032 if (from_kind == to_kind) return; 12923 if (from_kind == to_kind) return;
13033 // Don't update the site if to_kind isn't fast
13034 if (IsFastElementsKind(to_kind)) {
13035 UpdateAllocationSite(object, to_kind);
13036 }
13037 12924
13038 Isolate* isolate = object->GetIsolate(); 12925 // This method should never be called for any other case.
13039 if (object->elements() == isolate->heap()->empty_fixed_array() || 12926 DCHECK(IsFastElementsKind(from_kind));
13040 (IsFastSmiOrObjectElementsKind(from_kind) && 12927 DCHECK(IsFastElementsKind(to_kind));
13041 IsFastSmiOrObjectElementsKind(to_kind)) || 12928 DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
13042 (from_kind == FAST_DOUBLE_ELEMENTS && 12929
13043 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { 12930 UpdateAllocationSite(object, to_kind);
13044 DCHECK(from_kind != TERMINAL_FAST_ELEMENTS_KIND); 12931 if (object->elements() == object->GetHeap()->empty_fixed_array() ||
12932 IsFastDoubleElementsKind(from_kind) ==
12933 IsFastDoubleElementsKind(to_kind)) {
13045 // No change is needed to the elements() buffer, the transition 12934 // No change is needed to the elements() buffer, the transition
13046 // only requires a map change. 12935 // only requires a map change.
13047 Handle<Map> new_map = GetElementsTransitionMap(object, to_kind); 12936 Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
13048 MigrateToMap(object, new_map); 12937 MigrateToMap(object, new_map);
13049 if (FLAG_trace_elements_transitions) { 12938 if (FLAG_trace_elements_transitions) {
13050 Handle<FixedArrayBase> elms(object->elements()); 12939 Handle<FixedArrayBase> elms(object->elements());
13051 PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms); 12940 PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
13052 } 12941 }
13053 return; 12942 } else {
12943 DCHECK((IsFastSmiElementsKind(from_kind) &&
12944 IsFastDoubleElementsKind(to_kind)) ||
12945 (IsFastDoubleElementsKind(from_kind) &&
12946 IsFastObjectElementsKind(to_kind)));
12947 uint32_t c = static_cast<uint32_t>(object->elements()->length());
12948 ElementsAccessor::ForKind(to_kind)->GrowCapacityAndConvert(object, c);
13054 } 12949 }
13055
13056 Handle<FixedArrayBase> elms(object->elements());
13057 uint32_t capacity = static_cast<uint32_t>(elms->length());
13058 uint32_t length = capacity;
13059
13060 if (object->IsJSArray()) {
13061 Object* raw_length = Handle<JSArray>::cast(object)->length();
13062 if (raw_length->IsUndefined()) {
13063 // If length is undefined, then JSArray is being initialized and has no
13064 // elements, assume a length of zero.
13065 length = 0;
13066 } else {
13067 CHECK(raw_length->ToArrayLength(&length));
13068 }
13069 }
13070
13071 if (IsFastSmiElementsKind(from_kind) &&
13072 IsFastDoubleElementsKind(to_kind)) {
13073 SetFastDoubleElementsCapacityAndLength(object, capacity, length);
13074 JSObject::ValidateElements(object);
13075 return;
13076 }
13077
13078 if (IsFastDoubleElementsKind(from_kind) &&
13079 IsFastObjectElementsKind(to_kind)) {
13080 SetFastElementsCapacityAndLength(object, capacity, length,
13081 kDontAllowSmiElements);
13082 JSObject::ValidateElements(object);
13083 return;
13084 }
13085
13086 // This method should never be called for any other case than the ones
13087 // handled above.
13088 UNREACHABLE();
13089 } 12950 }
13090 12951
13091 12952
13092 // static 12953 // static
13093 bool Map::IsValidElementsTransition(ElementsKind from_kind, 12954 bool Map::IsValidElementsTransition(ElementsKind from_kind,
13094 ElementsKind to_kind) { 12955 ElementsKind to_kind) {
13095 // Transitions can't go backwards. 12956 // Transitions can't go backwards.
13096 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { 12957 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
13097 return false; 12958 return false;
13098 } 12959 }
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
13293 CHECK(JSArray::cast(this)->length()->ToArrayLength(&array_size)); 13154 CHECK(JSArray::cast(this)->length()->ToArrayLength(&array_size));
13294 } else { 13155 } else {
13295 array_size = dictionary->max_number_key(); 13156 array_size = dictionary->max_number_key();
13296 } 13157 }
13297 uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) * 13158 uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
13298 SeededNumberDictionary::kEntrySize; 13159 SeededNumberDictionary::kEntrySize;
13299 return 2 * dictionary_size >= array_size; 13160 return 2 * dictionary_size >= array_size;
13300 } 13161 }
13301 13162
13302 13163
13303 bool JSObject::ShouldConvertToFastDoubleElements( 13164 ElementsKind JSObject::BestFittingFastElementsKind() {
13304 bool* has_smi_only_elements) { 13165 if (HasSloppyArgumentsElements()) return FAST_HOLEY_ELEMENTS;
13305 *has_smi_only_elements = false; 13166 DCHECK(HasDictionaryElements());
13306 if (HasSloppyArgumentsElements()) return false; 13167 SeededNumberDictionary* dictionary = element_dictionary();
13307 if (FLAG_unbox_double_arrays) { 13168 ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
13308 DCHECK(HasDictionaryElements()); 13169 for (int i = 0; i < dictionary->Capacity(); i++) {
13309 SeededNumberDictionary* dictionary = element_dictionary(); 13170 Object* key = dictionary->KeyAt(i);
13310 bool found_double = false; 13171 if (key->IsNumber()) {
13311 for (int i = 0; i < dictionary->Capacity(); i++) { 13172 Object* value = dictionary->ValueAt(i);
13312 Object* key = dictionary->KeyAt(i); 13173 if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS;
13313 if (key->IsNumber()) { 13174 if (!value->IsSmi()) {
13314 Object* value = dictionary->ValueAt(i); 13175 if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS;
13315 if (!value->IsNumber()) return false; 13176 kind = FAST_HOLEY_DOUBLE_ELEMENTS;
13316 if (!value->IsSmi()) {
13317 found_double = true;
13318 }
13319 } 13177 }
13320 } 13178 }
13321 *has_smi_only_elements = !found_double;
13322 return found_double;
13323 } else {
13324 return false;
13325 } 13179 }
13180 return kind;
13326 } 13181 }
13327 13182
13328 13183
13329 // Certain compilers request function template instantiation when they 13184 // Certain compilers request function template instantiation when they
13330 // see the definition of the other template functions in the 13185 // see the definition of the other template functions in the
13331 // class. This requires us to have the template functions put 13186 // class. This requires us to have the template functions put
13332 // together, so even though this function belongs in objects-debug.cc, 13187 // together, so even though this function belongs in objects-debug.cc,
13333 // we keep it here instead to satisfy certain compilers. 13188 // we keep it here instead to satisfy certain compilers.
13334 #ifdef OBJECT_PRINT 13189 #ifdef OBJECT_PRINT
13335 template <typename Derived, typename Shape, typename Key> 13190 template <typename Derived, typename Shape, typename Key>
(...skipping 3306 matching lines...) Expand 10 before | Expand all | Expand 10 after
16642 Handle<Object> new_value) { 16497 Handle<Object> new_value) {
16643 if (cell->value() != *new_value) { 16498 if (cell->value() != *new_value) {
16644 cell->set_value(*new_value); 16499 cell->set_value(*new_value);
16645 Isolate* isolate = cell->GetIsolate(); 16500 Isolate* isolate = cell->GetIsolate();
16646 cell->dependent_code()->DeoptimizeDependentCodeGroup( 16501 cell->dependent_code()->DeoptimizeDependentCodeGroup(
16647 isolate, DependentCode::kPropertyCellChangedGroup); 16502 isolate, DependentCode::kPropertyCellChangedGroup);
16648 } 16503 }
16649 } 16504 }
16650 } // namespace internal 16505 } // namespace internal
16651 } // namespace v8 16506 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/runtime/runtime-array.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698