OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |