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

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') | no next file » | 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 11784 matching lines...) Expand 10 before | Expand all | Expand 10 after
11795 11795
11796 os << "RelocInfo (size = " << relocation_size() << ")\n"; 11796 os << "RelocInfo (size = " << relocation_size() << ")\n";
11797 for (RelocIterator it(this); !it.done(); it.next()) { 11797 for (RelocIterator it(this); !it.done(); it.next()) {
11798 it.rinfo()->Print(GetIsolate(), os); 11798 it.rinfo()->Print(GetIsolate(), os);
11799 } 11799 }
11800 os << "\n"; 11800 os << "\n";
11801 } 11801 }
11802 #endif // ENABLE_DISASSEMBLER 11802 #endif // ENABLE_DISASSEMBLER
11803 11803
11804 11804
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 11805 // static
11889 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) { 11806 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
11890 DCHECK(capacity >= 0); 11807 DCHECK(capacity >= 0);
11891 array->GetIsolate()->factory()->NewJSArrayStorage( 11808 array->GetIsolate()->factory()->NewJSArrayStorage(
11892 array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE); 11809 array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
11893 } 11810 }
11894 11811
11895 11812
11896 // Returns false if the passed-in index is marked non-configurable, which will 11813 // 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 11814 // 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)); 12348 FixedArray* arguments = FixedArray::cast(elements->get(1));
12432 return arguments->IsDictionary(); 12349 return arguments->IsDictionary();
12433 } 12350 }
12434 12351
12435 12352
12436 void JSObject::AddFastElement(Handle<JSObject> object, uint32_t index, 12353 void JSObject::AddFastElement(Handle<JSObject> object, uint32_t index,
12437 Handle<Object> value) { 12354 Handle<Object> value) {
12438 DCHECK(object->HasFastSmiOrObjectElements() || 12355 DCHECK(object->HasFastSmiOrObjectElements() ||
12439 object->HasFastArgumentsElements()); 12356 object->HasFastArgumentsElements());
12440 12357
12441 Isolate* isolate = object->GetIsolate();
12442
12443 Handle<FixedArray> backing_store(FixedArray::cast(object->elements())); 12358 Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
12444 if (object->HasSloppyArgumentsElements()) { 12359 if (object->HasSloppyArgumentsElements()) {
12445 backing_store = handle(FixedArray::cast(backing_store->get(1))); 12360 backing_store = handle(FixedArray::cast(backing_store->get(1)));
12446 } else { 12361 } 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); 12362 backing_store = EnsureWritableFastElements(object);
12452 } 12363 }
12453 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); 12364 uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12454 12365
12455 uint32_t new_capacity = capacity;
12456 // Check if the length property of this object needs to be updated. 12366 // Check if the length property of this object needs to be updated.
12457 uint32_t array_length = 0; 12367 uint32_t array_length = 0;
12458 bool must_update_array_length = false; 12368 bool must_update_array_length = false;
12459 bool introduces_holes = true; 12369 bool introduces_holes = true;
12460 if (object->IsJSArray()) { 12370 if (object->IsJSArray()) {
12461 CHECK( 12371 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&array_length));
12462 Handle<JSArray>::cast(object)->length()->ToArrayLength(&array_length));
12463 introduces_holes = index > array_length; 12372 introduces_holes = index > array_length;
12464 if (index >= array_length) { 12373 if (index >= array_length) {
12465 must_update_array_length = true; 12374 must_update_array_length = true;
12466 array_length = index + 1; 12375 array_length = index + 1;
12467 } 12376 }
12468 } else { 12377 } else {
12469 introduces_holes = index >= capacity; 12378 introduces_holes = index >= capacity;
12470 } 12379 }
12471 12380
12472 // If the array is growing, and it's not growth by a single element at the 12381 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 12382 // Check if the capacity of the backing store needs to be increased, or if
12481 // a transition to slow elements is necessary. 12383 // a transition to slow elements is necessary.
12482 if (index >= capacity) { 12384 if (index >= capacity) {
12483 bool convert_to_slow = true; 12385 bool convert_to_slow = true;
12484 if ((index - capacity) < kMaxGap) { 12386 if ((index - capacity) < kMaxGap) {
12485 new_capacity = NewElementsCapacity(index + 1); 12387 new_capacity = NewElementsCapacity(index + 1);
12486 DCHECK(new_capacity > index); 12388 DCHECK_LT(index, new_capacity);
12487 if (!object->ShouldConvertToSlowElements(new_capacity)) { 12389 convert_to_slow = object->ShouldConvertToSlowElements(new_capacity);
12488 convert_to_slow = false;
12489 }
12490 } 12390 }
12491 if (convert_to_slow) { 12391 if (convert_to_slow) {
12492 NormalizeElements(object); 12392 NormalizeElements(object);
12493 AddDictionaryElement(object, index, value, NONE); 12393 AddDictionaryElement(object, index, value, NONE);
12494 return; 12394 return;
12495 } 12395 }
12496 } 12396 }
12497 12397
12498 if (object->HasFastSmiElements() && !value->IsSmi()) { 12398 if (object->HasFastSmiElements() && !value->IsSmi()) {
12499 // Convert to fast double elements if appropriate. 12399 // Convert to fast double elements if appropriate.
12500 if (value->IsNumber()) { 12400 if (value->IsNumber()) {
12501 // Consider fixing the boilerplate as well if we have one. 12401 ElementsKind to_kind =
12502 ElementsKind to_kind = IsHoleyElementsKind(object->GetElementsKind()) 12402 introduces_holes ? FAST_HOLEY_DOUBLE_ELEMENTS : FAST_DOUBLE_ELEMENTS;
12503 ? FAST_HOLEY_DOUBLE_ELEMENTS 12403 ElementsAccessor* accessor = ElementsAccessor::ForKind(to_kind);
12504 : FAST_DOUBLE_ELEMENTS; 12404 accessor->GrowCapacityAndConvert(object, new_capacity);
12505 12405 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; 12406 return;
12513 } 12407 }
12514 12408
12515 // Change elements kind from Smi-only to generic FAST if necessary. 12409 // Change elements kind from Smi-only to generic FAST if necessary.
12516 ElementsKind kind = object->HasFastHoleyElements() 12410 ElementsKind kind = introduces_holes || object->HasFastHoleyElements()
12517 ? FAST_HOLEY_ELEMENTS 12411 ? FAST_HOLEY_ELEMENTS
12518 : FAST_ELEMENTS; 12412 : FAST_ELEMENTS;
12519 12413
12520 UpdateAllocationSite(object, kind); 12414 UpdateAllocationSite(object, kind);
12521 Handle<Map> new_map = GetElementsTransitionMap(object, kind); 12415 Handle<Map> new_map = GetElementsTransitionMap(object, kind);
12522 JSObject::MigrateToMap(object, new_map); 12416 JSObject::MigrateToMap(object, new_map);
12523 DCHECK(IsFastObjectElementsKind(object->GetElementsKind())); 12417 DCHECK(IsFastObjectElementsKind(object->GetElementsKind()));
12418 } else if (introduces_holes && !object->HasFastHoleyElements()) {
12419 // If the array is growing, and it's not growth by a single element at the
12420 // end, make sure that the ElementsKind is HOLEY.
12421 ElementsKind transitioned_kind =
12422 GetHoleyElementsKind(object->GetElementsKind());
12423 TransitionElementsKind(object, transitioned_kind);
12524 } 12424 }
12525 12425
12526 // Increase backing store capacity if that's been decided previously. 12426 // Increase backing store capacity if that's been decided previously.
12527 // Otherwise, set the new element and length. 12427 if (capacity != new_capacity) {
12528 if (new_capacity == capacity) { 12428 DCHECK(!(value->IsSmi() && object->HasFastDoubleElements()));
Jakob Kummerow 2015/06/22 17:03:02 AFAICS you can DCHECK(!object->HasFastDoubleElemen
Toon Verwaest 2015/06/22 18:31:01 Done.
12529 DCHECK(object->elements()->IsFixedArray()); 12429 ElementsAccessor* accessor =
12530 backing_store->set(index, *value); 12430 value->IsSmi() || object->HasSloppyArgumentsElements()
12531 if (must_update_array_length) { 12431 ? object->GetElementsAccessor()
12532 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length)); 12432 : ElementsAccessor::ForKind(FAST_ELEMENTS);
12533 } 12433 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 } 12434 }
12435
12436 if (must_update_array_length) {
12437 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
12438 }
12439
12440 FixedArray* elements = FixedArray::cast(object->elements());
12441 if (object->HasSloppyArgumentsElements()) {
12442 elements = FixedArray::cast(elements->get(1));
12443 }
12444 elements->set(index, *value);
12445
12446 JSObject::ValidateElements(object);
12545 } 12447 }
12546 12448
12547 12449
12548 void JSObject::SetDictionaryArgumentsElement(Handle<JSObject> object, 12450 void JSObject::SetDictionaryArgumentsElement(Handle<JSObject> object,
12549 uint32_t index, 12451 uint32_t index,
12550 Handle<Object> value, 12452 Handle<Object> value,
12551 PropertyAttributes attributes) { 12453 PropertyAttributes attributes) {
12552 // TODO(verwaest): Handle with the elements accessor. 12454 // TODO(verwaest): Handle with the elements accessor.
12553 Isolate* isolate = object->GetIsolate(); 12455 Isolate* isolate = object->GetIsolate();
12554 12456
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
12694 12596
12695 // Attempt to put this object back in fast case. 12597 // Attempt to put this object back in fast case.
12696 if (object->ShouldConvertToFastElements()) { 12598 if (object->ShouldConvertToFastElements()) {
12697 uint32_t new_length = 0; 12599 uint32_t new_length = 0;
12698 if (object->IsJSArray()) { 12600 if (object->IsJSArray()) {
12699 CHECK( 12601 CHECK(
12700 Handle<JSArray>::cast(object)->length()->ToArrayLength(&new_length)); 12602 Handle<JSArray>::cast(object)->length()->ToArrayLength(&new_length));
12701 } else { 12603 } else {
12702 new_length = dictionary->max_number_key() + 1; 12604 new_length = dictionary->max_number_key() + 1;
12703 } 12605 }
12704 bool has_smi_only_elements = false; 12606 ElementsKind to_kind = object->BestFittingFastElementsKind();
12705 bool should_convert_to_fast_double_elements = 12607 ElementsAccessor* accessor = ElementsAccessor::ForKind(to_kind);
12706 object->ShouldConvertToFastDoubleElements(&has_smi_only_elements); 12608 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); 12609 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()) {
Jakob Kummerow 2015/06/22 17:03:02 I think you want to keep the '!'.
Toon Verwaest 2015/06/22 18:31:01 Done.
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()); 12690 JSObject::ValidateElements(object);
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 } 12691 }
12800 12692
12801 12693
12802 // static 12694 // static
12803 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, 12695 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
12804 uint32_t index, Handle<Object> value, 12696 uint32_t index, Handle<Object> value,
12805 LanguageMode language_mode) { 12697 LanguageMode language_mode) {
12806 Isolate* isolate = object->GetIsolate(); 12698 Isolate* isolate = object->GetIsolate();
12807 LookupIterator it(isolate, object, index); 12699 LookupIterator it(isolate, object, index);
12808 return SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED); 12700 return SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED);
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
13016 12908
13017 // Walk through to the Allocation Site 12909 // Walk through to the Allocation Site
13018 site = handle(memento->GetAllocationSite()); 12910 site = handle(memento->GetAllocationSite());
13019 } 12911 }
13020 AllocationSite::DigestTransitionFeedback(site, to_kind); 12912 AllocationSite::DigestTransitionFeedback(site, to_kind);
13021 } 12913 }
13022 12914
13023 12915
13024 void JSObject::TransitionElementsKind(Handle<JSObject> object, 12916 void JSObject::TransitionElementsKind(Handle<JSObject> object,
13025 ElementsKind to_kind) { 12917 ElementsKind to_kind) {
13026 ElementsKind from_kind = object->map()->elements_kind(); 12918 ElementsKind from_kind = object->GetElementsKind();
13027 12919
13028 if (IsFastHoleyElementsKind(from_kind)) { 12920 if (IsFastHoleyElementsKind(from_kind)) {
13029 to_kind = GetHoleyElementsKind(to_kind); 12921 to_kind = GetHoleyElementsKind(to_kind);
13030 } 12922 }
13031 12923
13032 if (from_kind == to_kind) return; 12924 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 12925
13038 Isolate* isolate = object->GetIsolate(); 12926 // This method should never be called for any other case.
13039 if (object->elements() == isolate->heap()->empty_fixed_array() || 12927 DCHECK(IsFastElementsKind(from_kind));
13040 (IsFastSmiOrObjectElementsKind(from_kind) && 12928 DCHECK(IsFastElementsKind(to_kind));
13041 IsFastSmiOrObjectElementsKind(to_kind)) || 12929 DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
13042 (from_kind == FAST_DOUBLE_ELEMENTS && 12930
13043 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { 12931 UpdateAllocationSite(object, to_kind);
13044 DCHECK(from_kind != TERMINAL_FAST_ELEMENTS_KIND); 12932 if (object->elements() == object->GetHeap()->empty_fixed_array() ||
12933 IsFastDoubleElementsKind(from_kind) ==
12934 IsFastDoubleElementsKind(to_kind)) {
13045 // No change is needed to the elements() buffer, the transition 12935 // No change is needed to the elements() buffer, the transition
13046 // only requires a map change. 12936 // only requires a map change.
13047 Handle<Map> new_map = GetElementsTransitionMap(object, to_kind); 12937 Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
13048 MigrateToMap(object, new_map); 12938 MigrateToMap(object, new_map);
13049 if (FLAG_trace_elements_transitions) { 12939 if (FLAG_trace_elements_transitions) {
13050 Handle<FixedArrayBase> elms(object->elements()); 12940 Handle<FixedArrayBase> elms(object->elements());
13051 PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms); 12941 PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
13052 } 12942 }
13053 return; 12943 } else {
12944 DCHECK((IsFastSmiElementsKind(from_kind) &&
12945 IsFastDoubleElementsKind(to_kind)) ||
12946 (IsFastDoubleElementsKind(from_kind) &&
12947 IsFastObjectElementsKind(to_kind)));
12948 uint32_t c = static_cast<uint32_t>(object->elements()->length());
12949 ElementsAccessor::ForKind(to_kind)->GrowCapacityAndConvert(object, c);
13054 } 12950 }
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 } 12951 }
13090 12952
13091 12953
13092 // static 12954 // static
13093 bool Map::IsValidElementsTransition(ElementsKind from_kind, 12955 bool Map::IsValidElementsTransition(ElementsKind from_kind,
13094 ElementsKind to_kind) { 12956 ElementsKind to_kind) {
13095 // Transitions can't go backwards. 12957 // Transitions can't go backwards.
13096 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { 12958 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
13097 return false; 12959 return false;
13098 } 12960 }
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
13293 CHECK(JSArray::cast(this)->length()->ToArrayLength(&array_size)); 13155 CHECK(JSArray::cast(this)->length()->ToArrayLength(&array_size));
13294 } else { 13156 } else {
13295 array_size = dictionary->max_number_key(); 13157 array_size = dictionary->max_number_key();
13296 } 13158 }
13297 uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) * 13159 uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
13298 SeededNumberDictionary::kEntrySize; 13160 SeededNumberDictionary::kEntrySize;
13299 return 2 * dictionary_size >= array_size; 13161 return 2 * dictionary_size >= array_size;
13300 } 13162 }
13301 13163
13302 13164
13303 bool JSObject::ShouldConvertToFastDoubleElements( 13165 ElementsKind JSObject::BestFittingFastElementsKind() {
13304 bool* has_smi_only_elements) { 13166 if (HasSloppyArgumentsElements()) return FAST_HOLEY_ELEMENTS;
13305 *has_smi_only_elements = false; 13167 DCHECK(HasDictionaryElements());
13306 if (HasSloppyArgumentsElements()) return false; 13168 SeededNumberDictionary* dictionary = element_dictionary();
13307 if (FLAG_unbox_double_arrays) { 13169 ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
13308 DCHECK(HasDictionaryElements()); 13170 for (int i = 0; i < dictionary->Capacity(); i++) {
13309 SeededNumberDictionary* dictionary = element_dictionary(); 13171 Object* key = dictionary->KeyAt(i);
13310 bool found_double = false; 13172 if (key->IsNumber()) {
13311 for (int i = 0; i < dictionary->Capacity(); i++) { 13173 Object* value = dictionary->ValueAt(i);
13312 Object* key = dictionary->KeyAt(i); 13174 if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS;
13313 if (key->IsNumber()) { 13175 if (!value->IsSmi()) {
13314 Object* value = dictionary->ValueAt(i); 13176 if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS;
13315 if (!value->IsNumber()) return false; 13177 kind = FAST_HOLEY_DOUBLE_ELEMENTS;
13316 if (!value->IsSmi()) {
13317 found_double = true;
13318 }
13319 } 13178 }
13320 } 13179 }
13321 *has_smi_only_elements = !found_double;
13322 return found_double;
13323 } else {
13324 return false;
13325 } 13180 }
13181 return kind;
13326 } 13182 }
13327 13183
13328 13184
13329 // Certain compilers request function template instantiation when they 13185 // Certain compilers request function template instantiation when they
13330 // see the definition of the other template functions in the 13186 // see the definition of the other template functions in the
13331 // class. This requires us to have the template functions put 13187 // class. This requires us to have the template functions put
13332 // together, so even though this function belongs in objects-debug.cc, 13188 // together, so even though this function belongs in objects-debug.cc,
13333 // we keep it here instead to satisfy certain compilers. 13189 // we keep it here instead to satisfy certain compilers.
13334 #ifdef OBJECT_PRINT 13190 #ifdef OBJECT_PRINT
13335 template <typename Derived, typename Shape, typename Key> 13191 template <typename Derived, typename Shape, typename Key>
(...skipping 3306 matching lines...) Expand 10 before | Expand all | Expand 10 after
16642 Handle<Object> new_value) { 16498 Handle<Object> new_value) {
16643 if (cell->value() != *new_value) { 16499 if (cell->value() != *new_value) {
16644 cell->set_value(*new_value); 16500 cell->set_value(*new_value);
16645 Isolate* isolate = cell->GetIsolate(); 16501 Isolate* isolate = cell->GetIsolate();
16646 cell->dependent_code()->DeoptimizeDependentCodeGroup( 16502 cell->dependent_code()->DeoptimizeDependentCodeGroup(
16647 isolate, DependentCode::kPropertyCellChangedGroup); 16503 isolate, DependentCode::kPropertyCellChangedGroup);
16648 } 16504 }
16649 } 16505 }
16650 } // namespace internal 16506 } // namespace internal
16651 } // namespace v8 16507 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698