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

Side by Side Diff: src/objects.cc

Issue 1177043012: More cleanly separate adding from setting elements (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 11772 matching lines...) Expand 10 before | Expand all | Expand 10 after
11783 if (IsHoleyElementsKind(elements_kind)) { 11783 if (IsHoleyElementsKind(elements_kind)) {
11784 new_elements_kind = FAST_HOLEY_ELEMENTS; 11784 new_elements_kind = FAST_HOLEY_ELEMENTS;
11785 } else { 11785 } else {
11786 new_elements_kind = FAST_ELEMENTS; 11786 new_elements_kind = FAST_ELEMENTS;
11787 } 11787 }
11788 } 11788 }
11789 Handle<FixedArrayBase> old_elements(object->elements()); 11789 Handle<FixedArrayBase> old_elements(object->elements());
11790 ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind); 11790 ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind);
11791 accessor->CopyElements(object, new_elements, elements_kind); 11791 accessor->CopyElements(object, new_elements, elements_kind);
11792 11792
11793 if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) { 11793 if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) {
11794 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(old_elements);
11795 parameter_map->set(1, *new_elements);
11796 } else {
11794 Handle<Map> new_map = (new_elements_kind != elements_kind) 11797 Handle<Map> new_map = (new_elements_kind != elements_kind)
11795 ? GetElementsTransitionMap(object, new_elements_kind) 11798 ? GetElementsTransitionMap(object, new_elements_kind)
11796 : handle(object->map()); 11799 : handle(object->map());
11797 JSObject::ValidateElements(object); 11800 JSObject::ValidateElements(object);
11798 JSObject::SetMapAndElements(object, new_map, new_elements); 11801 JSObject::SetMapAndElements(object, new_map, new_elements);
11799 11802
11800 // Transition through the allocation site as well if present. 11803 // Transition through the allocation site as well if present.
11801 JSObject::UpdateAllocationSite(object, new_elements_kind); 11804 JSObject::UpdateAllocationSite(object, new_elements_kind);
11802 } else {
11803 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(old_elements);
11804 parameter_map->set(1, *new_elements);
11805 } 11805 }
11806 11806
11807 if (FLAG_trace_elements_transitions) { 11807 if (FLAG_trace_elements_transitions) {
11808 PrintElementsTransition(stdout, object, elements_kind, old_elements, 11808 PrintElementsTransition(stdout, object, elements_kind, old_elements,
11809 object->GetElementsKind(), new_elements); 11809 object->GetElementsKind(), new_elements);
11810 } 11810 }
11811 11811
11812 return new_elements; 11812 return new_elements;
11813 } 11813 }
11814 11814
(...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after
12420 if (!elements()->IsFixedArray()) return false; 12420 if (!elements()->IsFixedArray()) return false;
12421 FixedArray* elements = FixedArray::cast(this->elements()); 12421 FixedArray* elements = FixedArray::cast(this->elements());
12422 if (elements->map() != heap->sloppy_arguments_elements_map()) { 12422 if (elements->map() != heap->sloppy_arguments_elements_map()) {
12423 return false; 12423 return false;
12424 } 12424 }
12425 FixedArray* arguments = FixedArray::cast(elements->get(1)); 12425 FixedArray* arguments = FixedArray::cast(elements->get(1));
12426 return arguments->IsDictionary(); 12426 return arguments->IsDictionary();
12427 } 12427 }
12428 12428
12429 12429
12430 void JSObject::SetFastElement(Handle<JSObject> object, uint32_t index, 12430 void JSObject::AddFastElement(Handle<JSObject> object, uint32_t index,
12431 Handle<Object> value) { 12431 Handle<Object> value) {
12432 DCHECK(object->HasFastSmiOrObjectElements() || 12432 DCHECK(object->HasFastSmiOrObjectElements() ||
12433 object->HasFastArgumentsElements()); 12433 object->HasFastArgumentsElements());
12434 12434
12435 Isolate* isolate = object->GetIsolate(); 12435 Isolate* isolate = object->GetIsolate();
12436 12436
12437 // Array optimizations rely on the prototype lookups of Array objects always
12438 // returning undefined. If there is a store to the initial prototype object,
12439 // make sure all of these optimizations are invalidated.
12440 isolate->UpdateArrayProtectorOnSetElement(object);
12441
12442 Handle<FixedArray> backing_store(FixedArray::cast(object->elements())); 12437 Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
12443 if (object->HasSloppyArgumentsElements()) { 12438 if (object->HasSloppyArgumentsElements()) {
12444 backing_store = handle(FixedArray::cast(backing_store->get(1))); 12439 backing_store = handle(FixedArray::cast(backing_store->get(1)));
12445 } else { 12440 } else {
12441 // Array optimizations rely on the prototype lookups of Array objects always
12442 // returning undefined. If there is a store to the initial prototype object,
12443 // make sure all of these optimizations are invalidated.
12444 isolate->UpdateArrayProtectorOnSetElement(object);
12446 backing_store = EnsureWritableFastElements(object); 12445 backing_store = EnsureWritableFastElements(object);
12447 } 12446 }
12448 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); 12447 uint32_t capacity = static_cast<uint32_t>(backing_store->length());
12449 12448
12450 uint32_t new_capacity = capacity; 12449 uint32_t new_capacity = capacity;
12451 // Check if the length property of this object needs to be updated. 12450 // Check if the length property of this object needs to be updated.
12452 uint32_t array_length = 0; 12451 uint32_t array_length = 0;
12453 bool must_update_array_length = false; 12452 bool must_update_array_length = false;
12454 bool introduces_holes = true; 12453 bool introduces_holes = true;
12455 if (object->IsJSArray()) { 12454 if (object->IsJSArray()) {
12456 CHECK( 12455 CHECK(
12457 Handle<JSArray>::cast(object)->length()->ToArrayLength(&array_length)); 12456 Handle<JSArray>::cast(object)->length()->ToArrayLength(&array_length));
12458 introduces_holes = index > array_length; 12457 introduces_holes = index > array_length;
12459 if (index >= array_length) { 12458 if (index >= array_length) {
12460 must_update_array_length = true; 12459 must_update_array_length = true;
12461 array_length = index + 1; 12460 array_length = index + 1;
12462 } 12461 }
12463 } else { 12462 } else {
12464 introduces_holes = index >= capacity; 12463 introduces_holes = index >= capacity;
12465 } 12464 }
12466 12465
12467 // If the array is growing, and it's not growth by a single element at the 12466 // If the array is growing, and it's not growth by a single element at the
12468 // end, make sure that the ElementsKind is HOLEY. 12467 // end, make sure that the ElementsKind is HOLEY.
12469 ElementsKind elements_kind = object->GetElementsKind(); 12468 if (introduces_holes && !IsFastHoleyElementsKind(object->GetElementsKind())) {
12470 if (introduces_holes && 12469 ElementsKind transitioned_kind =
12471 IsFastElementsKind(elements_kind) && 12470 GetHoleyElementsKind(object->GetElementsKind());
12472 !IsFastHoleyElementsKind(elements_kind)) {
12473 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12474 TransitionElementsKind(object, transitioned_kind); 12471 TransitionElementsKind(object, transitioned_kind);
12475 } 12472 }
12476 12473
12477 // Check if the capacity of the backing store needs to be increased, or if 12474 // Check if the capacity of the backing store needs to be increased, or if
12478 // a transition to slow elements is necessary. 12475 // a transition to slow elements is necessary.
12479 if (index >= capacity) { 12476 if (index >= capacity) {
12480 bool convert_to_slow = true; 12477 bool convert_to_slow = true;
12481 if ((index - capacity) < kMaxGap) { 12478 if ((index - capacity) < kMaxGap) {
12482 new_capacity = NewElementsCapacity(index + 1); 12479 new_capacity = NewElementsCapacity(index + 1);
12483 DCHECK(new_capacity > index); 12480 DCHECK(new_capacity > index);
12484 if (!object->ShouldConvertToSlowElements(new_capacity)) { 12481 if (!object->ShouldConvertToSlowElements(new_capacity)) {
12485 convert_to_slow = false; 12482 convert_to_slow = false;
12486 } 12483 }
12487 } 12484 }
12488 if (convert_to_slow) { 12485 if (convert_to_slow) {
12489 NormalizeElements(object); 12486 NormalizeElements(object);
12490 SetDictionaryElement(object, index, value, NONE); 12487 AddDictionaryElement(object, index, value, NONE);
12491 return; 12488 return;
12492 } 12489 }
12493 } 12490 }
12491
12494 // Convert to fast double elements if appropriate. 12492 // Convert to fast double elements if appropriate.
12495 if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { 12493 if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
12496 // Consider fixing the boilerplate as well if we have one. 12494 // Consider fixing the boilerplate as well if we have one.
12497 ElementsKind to_kind = IsHoleyElementsKind(elements_kind) 12495 ElementsKind to_kind = IsHoleyElementsKind(object->GetElementsKind())
12498 ? FAST_HOLEY_DOUBLE_ELEMENTS 12496 ? FAST_HOLEY_DOUBLE_ELEMENTS
12499 : FAST_DOUBLE_ELEMENTS; 12497 : FAST_DOUBLE_ELEMENTS;
12500 12498
12501 UpdateAllocationSite(object, to_kind); 12499 UpdateAllocationSite(object, to_kind);
12502 12500
12503 SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length); 12501 SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length);
12504 FixedDoubleArray::cast(object->elements())->set(index, value->Number()); 12502 FixedDoubleArray::cast(object->elements())->set(index, value->Number());
12505 JSObject::ValidateElements(object); 12503 JSObject::ValidateElements(object);
12506 return; 12504 return;
12507 } 12505 }
12506
12508 // Change elements kind from Smi-only to generic FAST if necessary. 12507 // Change elements kind from Smi-only to generic FAST if necessary.
12509 if (object->HasFastSmiElements() && !value->IsSmi()) { 12508 if (object->HasFastSmiElements() && !value->IsSmi()) {
12510 ElementsKind kind = object->HasFastHoleyElements() 12509 ElementsKind kind = object->HasFastHoleyElements()
12511 ? FAST_HOLEY_ELEMENTS 12510 ? FAST_HOLEY_ELEMENTS
12512 : FAST_ELEMENTS; 12511 : FAST_ELEMENTS;
12513 12512
12514 UpdateAllocationSite(object, kind); 12513 UpdateAllocationSite(object, kind);
12515 Handle<Map> new_map = GetElementsTransitionMap(object, kind); 12514 Handle<Map> new_map = GetElementsTransitionMap(object, kind);
12516 JSObject::MigrateToMap(object, new_map); 12515 JSObject::MigrateToMap(object, new_map);
12517 DCHECK(IsFastObjectElementsKind(object->GetElementsKind())); 12516 DCHECK(IsFastObjectElementsKind(object->GetElementsKind()));
12518 } 12517 }
12518
12519 // Increase backing store capacity if that's been decided previously. 12519 // Increase backing store capacity if that's been decided previously.
12520 if (new_capacity != capacity) { 12520 if (new_capacity != capacity) {
12521 SetFastElementsCapacitySmiMode smi_mode = 12521 SetFastElementsCapacitySmiMode smi_mode =
12522 value->IsSmi() && object->HasFastSmiElements() 12522 value->IsSmi() && object->HasFastSmiElements()
12523 ? kAllowSmiElements 12523 ? kAllowSmiElements
12524 : kDontAllowSmiElements; 12524 : kDontAllowSmiElements;
12525 Handle<FixedArray> new_elements = 12525 Handle<FixedArray> new_elements =
12526 SetFastElementsCapacityAndLength(object, new_capacity, array_length, 12526 SetFastElementsCapacityAndLength(object, new_capacity, array_length,
12527 smi_mode); 12527 smi_mode);
12528 new_elements->set(index, *value); 12528 new_elements->set(index, *value);
(...skipping 15 matching lines...) Expand all
12544 PropertyAttributes attributes) { 12544 PropertyAttributes attributes) {
12545 // TODO(verwaest): Handle with the elements accessor. 12545 // TODO(verwaest): Handle with the elements accessor.
12546 Isolate* isolate = object->GetIsolate(); 12546 Isolate* isolate = object->GetIsolate();
12547 12547
12548 DCHECK(object->HasSloppyArgumentsElements()); 12548 DCHECK(object->HasSloppyArgumentsElements());
12549 12549
12550 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); 12550 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
12551 uint32_t length = parameter_map->length(); 12551 uint32_t length = parameter_map->length();
12552 Handle<Object> probe = 12552 Handle<Object> probe =
12553 index < length - 2 12553 index < length - 2
12554 ? Handle<Object>(parameter_map->get(index + 2), isolate) 12554 ? handle(parameter_map->get(index + 2), isolate)
12555 : Handle<Object>(); 12555 : Handle<Object>::cast(isolate->factory()->the_hole_value());
Jakob Kummerow 2015/06/18 11:32:47 nit: do you even need the cast?
12556 if (!probe.is_null() && !probe->IsTheHole()) { 12556 if (!probe->IsTheHole()) {
12557 Handle<Context> context(Context::cast(parameter_map->get(0))); 12557 Handle<Context> context(Context::cast(parameter_map->get(0)));
12558 int context_index = Handle<Smi>::cast(probe)->value(); 12558 int context_index = Handle<Smi>::cast(probe)->value();
12559 DCHECK(!context->get(context_index)->IsTheHole()); 12559 DCHECK(!context->get(context_index)->IsTheHole());
12560 context->set(context_index, *value); 12560 context->set(context_index, *value);
12561 12561
12562 if (attributes == NONE) return; 12562 if (attributes == NONE) return;
12563 12563
12564 // Redefining attributes of an aliased element destroys fast aliasing. 12564 // Redefining attributes of an aliased element destroys fast aliasing.
12565 parameter_map->set_the_hole(index + 2); 12565 parameter_map->set_the_hole(index + 2);
12566 // For elements that are still writable we re-establish slow aliasing. 12566 // For elements that are still writable we re-establish slow aliasing.
12567 if ((attributes & READ_ONLY) == 0) { 12567 if ((attributes & READ_ONLY) == 0) {
12568 value = Handle<Object>::cast( 12568 value = isolate->factory()->NewAliasedArgumentsEntry(context_index);
12569 isolate->factory()->NewAliasedArgumentsEntry(context_index));
12570 } 12569 }
12571 } 12570 DCHECK(parameter_map->get(1)->IsDictionary());
Jakob Kummerow 2015/06/18 11:32:47 Since this is something that callers must ensure,
12572 12571 AddDictionaryElement(object, index, value, attributes);
12573 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); 12572 } else {
12574 if (arguments->IsDictionary()) { 12573 DCHECK(parameter_map->get(1)->IsDictionary());
12575 SetDictionaryElement(object, index, value, attributes); 12574 SetDictionaryElement(object, index, value, attributes);
12576 } else {
12577 SetFastElement(object, index, value);
12578 } 12575 }
12579 } 12576 }
12580 12577
12578
12579 void JSObject::AddSloppyArgumentsElement(Handle<JSObject> object,
12580 uint32_t index, Handle<Object> value,
12581 PropertyAttributes attributes) {
12582 DCHECK(object->HasSloppyArgumentsElements());
12583
12584 // TODO(verwaest): Handle with the elements accessor.
12585 FixedArray* parameter_map = FixedArray::cast(object->elements());
12586
12587 #ifdef DEBUG
12588 uint32_t length = parameter_map->length();
12589 if (index < length - 2) {
12590 Object* probe = parameter_map->get(index + 2);
12591 DCHECK(probe->IsTheHole());
12592 }
12593 #endif
12594
12595 if (parameter_map->get(1)->IsDictionary()) {
12596 AddDictionaryElement(object, index, value, attributes);
12597 } else {
12598 AddFastElement(object, index, value);
12599 }
12600 }
12601
12581 12602
12582 void JSObject::SetDictionaryElement(Handle<JSObject> object, uint32_t index, 12603 void JSObject::SetDictionaryElement(Handle<JSObject> object, uint32_t index,
12583 Handle<Object> value, 12604 Handle<Object> value,
12584 PropertyAttributes attributes) { 12605 PropertyAttributes attributes) {
12585 // TODO(verwaest): Handle with the elements accessor. 12606 // TODO(verwaest): Handle with the elements accessor.
12586 Isolate* isolate = object->GetIsolate(); 12607 Isolate* isolate = object->GetIsolate();
12587 12608
12588 // Insert element in the dictionary. 12609 // Insert element in the dictionary.
12589 Handle<FixedArray> elements(FixedArray::cast(object->elements())); 12610 Handle<FixedArray> elements(FixedArray::cast(object->elements()));
12590 bool is_arguments = 12611 bool is_arguments =
12591 (elements->map() == isolate->heap()->sloppy_arguments_elements_map()); 12612 (elements->map() == isolate->heap()->sloppy_arguments_elements_map());
12592 12613
12593 DCHECK(object->HasDictionaryElements() || 12614 DCHECK(object->HasDictionaryElements() ||
12594 object->HasDictionaryArgumentsElements()); 12615 object->HasDictionaryArgumentsElements());
12595 12616
12596 Handle<SeededNumberDictionary> dictionary(is_arguments 12617 Handle<SeededNumberDictionary> dictionary(is_arguments
12597 ? SeededNumberDictionary::cast(elements->get(1)) 12618 ? SeededNumberDictionary::cast(elements->get(1))
12598 : SeededNumberDictionary::cast(*elements)); 12619 : SeededNumberDictionary::cast(*elements));
12599 12620
12600 int entry = dictionary->FindEntry(index); 12621 int entry = dictionary->FindEntry(index);
12601 if (entry != SeededNumberDictionary::kNotFound) { 12622 DCHECK_NE(SeededNumberDictionary::kNotFound, entry);
12623
12624 PropertyDetails details = dictionary->DetailsAt(entry);
12625 details = PropertyDetails(attributes, DATA, details.dictionary_index(),
12626 PropertyCellType::kNoCell);
12627 dictionary->DetailsAtPut(entry, details);
12628
12629 // Elements of the arguments object in slow mode might be slow aliases.
12630 if (is_arguments) {
12602 Handle<Object> element(dictionary->ValueAt(entry), isolate); 12631 Handle<Object> element(dictionary->ValueAt(entry), isolate);
12603 PropertyDetails details = dictionary->DetailsAt(entry); 12632 if (element->IsAliasedArgumentsEntry()) {
12604 DCHECK(details.IsConfigurable() || !details.IsReadOnly() ||
12605 element->IsTheHole());
12606 dictionary->UpdateMaxNumberKey(index);
12607
12608 details = PropertyDetails(attributes, DATA, details.dictionary_index(),
12609 PropertyCellType::kNoCell);
12610 dictionary->DetailsAtPut(entry, details);
12611
12612 // Elements of the arguments object in slow mode might be slow aliases.
12613 if (is_arguments && element->IsAliasedArgumentsEntry()) {
12614 Handle<AliasedArgumentsEntry> entry = 12633 Handle<AliasedArgumentsEntry> entry =
12615 Handle<AliasedArgumentsEntry>::cast(element); 12634 Handle<AliasedArgumentsEntry>::cast(element);
12616 Handle<Context> context(Context::cast(elements->get(0))); 12635 Handle<Context> context(Context::cast(elements->get(0)));
12617 int context_index = entry->aliased_context_slot(); 12636 int context_index = entry->aliased_context_slot();
12618 DCHECK(!context->get(context_index)->IsTheHole()); 12637 DCHECK(!context->get(context_index)->IsTheHole());
12619 context->set(context_index, *value); 12638 context->set(context_index, *value);
12620 // For elements that are still writable we keep slow aliasing. 12639 // For elements that are still writable we keep slow aliasing.
12621 if (!details.IsReadOnly()) value = element; 12640 if (!details.IsReadOnly()) value = element;
12622 } 12641 }
12623 dictionary->ValueAtPut(entry, *value); 12642 }
12624 } else { 12643
12625 DCHECK(object->map()->is_extensible()); 12644 dictionary->ValueAtPut(entry, *value);
12626 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); 12645 }
12627 Handle<SeededNumberDictionary> new_dictionary = 12646
12628 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, 12647
12629 details); 12648 void JSObject::AddDictionaryElement(Handle<JSObject> object, uint32_t index,
12630 if (*dictionary != *new_dictionary) { 12649 Handle<Object> value,
12631 if (is_arguments) { 12650 PropertyAttributes attributes) {
12632 elements->set(1, *new_dictionary); 12651 // TODO(verwaest): Handle with the elements accessor.
12633 } else { 12652 Isolate* isolate = object->GetIsolate();
12634 object->set_elements(*new_dictionary); 12653
12635 } 12654 // Insert element in the dictionary.
12636 dictionary = new_dictionary; 12655 Handle<FixedArray> elements(FixedArray::cast(object->elements()));
12656 bool is_arguments =
12657 (elements->map() == isolate->heap()->sloppy_arguments_elements_map());
12658
12659 DCHECK(object->HasDictionaryElements() ||
12660 object->HasDictionaryArgumentsElements());
12661
12662 Handle<SeededNumberDictionary> dictionary(
12663 is_arguments ? SeededNumberDictionary::cast(elements->get(1))
12664 : SeededNumberDictionary::cast(*elements));
12665
12666 #ifdef DEBUG
12667 int entry = dictionary->FindEntry(index);
12668 DCHECK_EQ(SeededNumberDictionary::kNotFound, entry);
12669 DCHECK(object->map()->is_extensible());
12670 #endif
12671
12672 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
12673 Handle<SeededNumberDictionary> new_dictionary =
12674 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, details);
12675 if (*dictionary != *new_dictionary) {
12676 if (is_arguments) {
12677 elements->set(1, *new_dictionary);
12678 } else {
12679 object->set_elements(*new_dictionary);
12637 } 12680 }
12681 dictionary = new_dictionary;
12638 } 12682 }
12639 12683
12640 // Update the array length if this JSObject is an array. 12684 // Update the array length if this JSObject is an array.
12641 if (object->IsJSArray()) { 12685 if (object->IsJSArray()) {
12642 JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index, 12686 JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index,
12643 value); 12687 value);
12644 } 12688 }
12645 12689
12646 // Attempt to put this object back in fast case. 12690 // Attempt to put this object back in fast case.
12647 if (object->ShouldConvertToFastElements()) { 12691 if (object->ShouldConvertToFastElements()) {
(...skipping 20 matching lines...) Expand all
12668 #ifdef DEBUG 12712 #ifdef DEBUG
12669 if (FLAG_trace_normalization) { 12713 if (FLAG_trace_normalization) {
12670 OFStream os(stdout); 12714 OFStream os(stdout);
12671 os << "Object elements are fast case again:\n"; 12715 os << "Object elements are fast case again:\n";
12672 object->Print(os); 12716 object->Print(os);
12673 } 12717 }
12674 #endif 12718 #endif
12675 } 12719 }
12676 } 12720 }
12677 12721
12678 void JSObject::SetFastDoubleElement(Handle<JSObject> object, uint32_t index, 12722
12723 void JSObject::AddFastDoubleElement(Handle<JSObject> object, uint32_t index,
12679 Handle<Object> value) { 12724 Handle<Object> value) {
12680 DCHECK(object->HasFastDoubleElements()); 12725 DCHECK(object->HasFastDoubleElements());
12681 12726
12682 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements())); 12727 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements()));
12683 uint32_t elms_length = static_cast<uint32_t>(base_elms->length()); 12728 uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
12684 uint32_t length = elms_length; 12729 uint32_t length = elms_length;
12685 12730
12686 bool introduces_holes = true; 12731 bool introduces_holes = true;
12687 if (object->IsJSArray()) { 12732 if (object->IsJSArray()) {
12688 // In case of JSArray, the length does not equal the capacity. 12733 // In case of JSArray, the length does not equal the capacity.
12689 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(&length)); 12734 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(&length));
12690 introduces_holes = index > length; 12735 introduces_holes = index > length;
12691 } else { 12736 } else {
12692 introduces_holes = index >= elms_length; 12737 introduces_holes = index >= elms_length;
12693 } 12738 }
12694 12739
12695 // If the value object is not a heap number, switch to fast elements and try 12740 // If the value object is not a heap number, switch to fast elements and try
12696 // again. 12741 // again.
12697 if (!value->IsNumber()) { 12742 if (!value->IsNumber()) {
12698 SetFastElementsCapacityAndLength(object, elms_length, length, 12743 SetFastElementsCapacityAndLength(object, elms_length, length,
12699 kDontAllowSmiElements); 12744 kDontAllowSmiElements);
12700 SetFastElement(object, index, value); 12745 AddFastElement(object, index, value);
12701 return; 12746 return;
12702 } 12747 }
12703 12748
12704 // If the array is growing, and it's not growth by a single element at the 12749 // If the array is growing, and it's not growth by a single element at the
12705 // end, make sure that the ElementsKind is HOLEY. 12750 // end, make sure that the ElementsKind is HOLEY.
12706 ElementsKind elements_kind = object->GetElementsKind(); 12751 if (introduces_holes && !IsFastHoleyElementsKind(object->GetElementsKind())) {
12707 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) { 12752 ElementsKind transitioned_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
12708 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
12709 TransitionElementsKind(object, transitioned_kind); 12753 TransitionElementsKind(object, transitioned_kind);
12710 } 12754 }
12711 12755
12712 // Check whether there is extra space in the fixed array. 12756 // Check whether there is extra space in the fixed array.
12713 if (index < elms_length) { 12757 if (index < elms_length) {
12714 Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements())); 12758 Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements()));
12715 elms->set(index, value->Number()); 12759 elms->set(index, value->Number());
12716 if (object->IsJSArray()) { 12760 if (object->IsJSArray()) {
12717 // Update the length of the array if needed. 12761 // Update the length of the array if needed.
12718 uint32_t array_length = 0; 12762 uint32_t array_length = 0;
(...skipping 20 matching lines...) Expand all
12739 } 12783 }
12740 12784
12741 // Otherwise default to slow case. 12785 // Otherwise default to slow case.
12742 DCHECK(object->HasFastDoubleElements()); 12786 DCHECK(object->HasFastDoubleElements());
12743 DCHECK(object->map()->has_fast_double_elements()); 12787 DCHECK(object->map()->has_fast_double_elements());
12744 DCHECK(object->elements()->IsFixedDoubleArray() || 12788 DCHECK(object->elements()->IsFixedDoubleArray() ||
12745 object->elements()->length() == 0); 12789 object->elements()->length() == 0);
12746 12790
12747 NormalizeElements(object); 12791 NormalizeElements(object);
12748 DCHECK(object->HasDictionaryElements()); 12792 DCHECK(object->HasDictionaryElements());
12749 SetDictionaryElement(object, index, value, NONE); 12793 AddDictionaryElement(object, index, value, NONE);
12750 } 12794 }
12751 12795
12752 12796
12753 // static 12797 // static
12754 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, 12798 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
12755 uint32_t index, Handle<Object> value, 12799 uint32_t index, Handle<Object> value,
12756 LanguageMode language_mode) { 12800 LanguageMode language_mode) {
12757 Isolate* isolate = object->GetIsolate(); 12801 Isolate* isolate = object->GetIsolate();
12758 LookupIterator it(isolate, object, index); 12802 LookupIterator it(isolate, object, index);
12759 return SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED); 12803 return SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED);
(...skipping 21 matching lines...) Expand all
12781 d->set_requires_slow_elements(); 12825 d->set_requires_slow_elements();
12782 } 12826 }
12783 12827
12784 Handle<Object> result = value; 12828 Handle<Object> result = value;
12785 12829
12786 switch (receiver->GetElementsKind()) { 12830 switch (receiver->GetElementsKind()) {
12787 case FAST_SMI_ELEMENTS: 12831 case FAST_SMI_ELEMENTS:
12788 case FAST_ELEMENTS: 12832 case FAST_ELEMENTS:
12789 case FAST_HOLEY_SMI_ELEMENTS: 12833 case FAST_HOLEY_SMI_ELEMENTS:
12790 case FAST_HOLEY_ELEMENTS: 12834 case FAST_HOLEY_ELEMENTS:
12791 SetFastElement(receiver, index, value); 12835 AddFastElement(receiver, index, value);
12792 break; 12836 break;
12793 case FAST_DOUBLE_ELEMENTS: 12837 case FAST_DOUBLE_ELEMENTS:
12794 case FAST_HOLEY_DOUBLE_ELEMENTS: 12838 case FAST_HOLEY_DOUBLE_ELEMENTS:
12795 SetFastDoubleElement(receiver, index, value); 12839 AddFastDoubleElement(receiver, index, value);
12796 break; 12840 break;
12797 12841
12798 case DICTIONARY_ELEMENTS: 12842 case DICTIONARY_ELEMENTS:
12799 SetDictionaryElement(receiver, index, value, attributes); 12843 AddDictionaryElement(receiver, index, value, attributes);
12800 break; 12844 break;
12801 case SLOPPY_ARGUMENTS_ELEMENTS: 12845 case SLOPPY_ARGUMENTS_ELEMENTS:
12802 SetSloppyArgumentsElement(receiver, index, value, attributes); 12846 AddSloppyArgumentsElement(receiver, index, value, attributes);
12803 break; 12847 break;
12804 12848
12805 // Elements cannot be added to typed arrays. 12849 // Elements cannot be added to typed arrays.
12806 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 12850 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
12807 case EXTERNAL_##TYPE##_ELEMENTS: \ 12851 case EXTERNAL_##TYPE##_ELEMENTS: \
12808 case TYPE##_ELEMENTS: 12852 case TYPE##_ELEMENTS:
12809 12853
12810 TYPED_ARRAYS(TYPED_ARRAY_CASE) 12854 TYPED_ARRAYS(TYPED_ARRAY_CASE)
12811 12855
12812 #undef TYPED_ARRAY_CASE 12856 #undef TYPED_ARRAY_CASE
(...skipping 3849 matching lines...) Expand 10 before | Expand all | Expand 10 after
16662 Handle<Object> new_value) { 16706 Handle<Object> new_value) {
16663 if (cell->value() != *new_value) { 16707 if (cell->value() != *new_value) {
16664 cell->set_value(*new_value); 16708 cell->set_value(*new_value);
16665 Isolate* isolate = cell->GetIsolate(); 16709 Isolate* isolate = cell->GetIsolate();
16666 cell->dependent_code()->DeoptimizeDependentCodeGroup( 16710 cell->dependent_code()->DeoptimizeDependentCodeGroup(
16667 isolate, DependentCode::kPropertyCellChangedGroup); 16711 isolate, DependentCode::kPropertyCellChangedGroup);
16668 } 16712 }
16669 } 16713 }
16670 } // namespace internal 16714 } // namespace internal
16671 } // namespace v8 16715 } // 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