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); |
12529 JSObject::ValidateElements(object); | 12529 JSObject::ValidateElements(object); |
12530 return; | 12530 return; |
12531 } | 12531 } |
12532 | 12532 |
12533 // Finally, set the new element and length. | 12533 // Finally, set the new element and length. |
12534 DCHECK(object->elements()->IsFixedArray()); | 12534 DCHECK(object->elements()->IsFixedArray()); |
12535 backing_store->set(index, *value); | 12535 backing_store->set(index, *value); |
12536 if (must_update_array_length) { | 12536 if (must_update_array_length) { |
12537 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length)); | 12537 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length)); |
12538 } | 12538 } |
12539 } | 12539 } |
12540 | 12540 |
12541 | 12541 |
12542 void JSObject::SetSloppyArgumentsElement(Handle<JSObject> object, | 12542 void JSObject::SetDictionaryArgumentsElement(Handle<JSObject> object, |
12543 uint32_t index, Handle<Object> value, | 12543 uint32_t index, |
12544 PropertyAttributes attributes) { | 12544 Handle<Object> value, |
| 12545 PropertyAttributes attributes) { |
12545 // TODO(verwaest): Handle with the elements accessor. | 12546 // TODO(verwaest): Handle with the elements accessor. |
12546 Isolate* isolate = object->GetIsolate(); | 12547 Isolate* isolate = object->GetIsolate(); |
12547 | 12548 |
12548 DCHECK(object->HasSloppyArgumentsElements()); | 12549 DCHECK(object->HasDictionaryArgumentsElements()); |
12549 | 12550 |
12550 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); | 12551 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); |
12551 uint32_t length = parameter_map->length(); | 12552 uint32_t length = parameter_map->length(); |
12552 Handle<Object> probe = | 12553 Handle<Object> probe = |
12553 index < length - 2 | 12554 index < length - 2 |
12554 ? Handle<Object>(parameter_map->get(index + 2), isolate) | 12555 ? handle(parameter_map->get(index + 2), isolate) |
12555 : Handle<Object>(); | 12556 : Handle<Object>::cast(isolate->factory()->the_hole_value()); |
12556 if (!probe.is_null() && !probe->IsTheHole()) { | 12557 if (!probe->IsTheHole()) { |
12557 Handle<Context> context(Context::cast(parameter_map->get(0))); | 12558 Handle<Context> context(Context::cast(parameter_map->get(0))); |
12558 int context_index = Handle<Smi>::cast(probe)->value(); | 12559 int context_index = Handle<Smi>::cast(probe)->value(); |
12559 DCHECK(!context->get(context_index)->IsTheHole()); | 12560 DCHECK(!context->get(context_index)->IsTheHole()); |
12560 context->set(context_index, *value); | 12561 context->set(context_index, *value); |
12561 | 12562 |
12562 if (attributes == NONE) return; | 12563 DCHECK_NE(NONE, attributes); |
12563 | 12564 |
12564 // Redefining attributes of an aliased element destroys fast aliasing. | 12565 // Redefining attributes of an aliased element destroys fast aliasing. |
12565 parameter_map->set_the_hole(index + 2); | 12566 parameter_map->set_the_hole(index + 2); |
12566 // For elements that are still writable we re-establish slow aliasing. | 12567 // For elements that are still writable we re-establish slow aliasing. |
12567 if ((attributes & READ_ONLY) == 0) { | 12568 if ((attributes & READ_ONLY) == 0) { |
12568 value = Handle<Object>::cast( | 12569 value = isolate->factory()->NewAliasedArgumentsEntry(context_index); |
12569 isolate->factory()->NewAliasedArgumentsEntry(context_index)); | |
12570 } | 12570 } |
12571 } | 12571 AddDictionaryElement(object, index, value, attributes); |
12572 | 12572 } else { |
12573 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); | |
12574 if (arguments->IsDictionary()) { | |
12575 SetDictionaryElement(object, index, value, attributes); | 12573 SetDictionaryElement(object, index, value, attributes); |
12576 } else { | |
12577 SetFastElement(object, index, value); | |
12578 } | 12574 } |
12579 } | 12575 } |
12580 | 12576 |
| 12577 |
| 12578 void JSObject::AddSloppyArgumentsElement(Handle<JSObject> object, |
| 12579 uint32_t index, Handle<Object> value, |
| 12580 PropertyAttributes attributes) { |
| 12581 DCHECK(object->HasSloppyArgumentsElements()); |
| 12582 |
| 12583 // TODO(verwaest): Handle with the elements accessor. |
| 12584 FixedArray* parameter_map = FixedArray::cast(object->elements()); |
| 12585 |
| 12586 #ifdef DEBUG |
| 12587 uint32_t length = parameter_map->length(); |
| 12588 if (index < length - 2) { |
| 12589 Object* probe = parameter_map->get(index + 2); |
| 12590 DCHECK(probe->IsTheHole()); |
| 12591 } |
| 12592 #endif |
| 12593 |
| 12594 if (parameter_map->get(1)->IsDictionary()) { |
| 12595 AddDictionaryElement(object, index, value, attributes); |
| 12596 } else { |
| 12597 AddFastElement(object, index, value); |
| 12598 } |
| 12599 } |
| 12600 |
12581 | 12601 |
12582 void JSObject::SetDictionaryElement(Handle<JSObject> object, uint32_t index, | 12602 void JSObject::SetDictionaryElement(Handle<JSObject> object, uint32_t index, |
12583 Handle<Object> value, | 12603 Handle<Object> value, |
12584 PropertyAttributes attributes) { | 12604 PropertyAttributes attributes) { |
12585 // TODO(verwaest): Handle with the elements accessor. | 12605 // TODO(verwaest): Handle with the elements accessor. |
12586 Isolate* isolate = object->GetIsolate(); | 12606 Isolate* isolate = object->GetIsolate(); |
12587 | 12607 |
12588 // Insert element in the dictionary. | 12608 // Insert element in the dictionary. |
12589 Handle<FixedArray> elements(FixedArray::cast(object->elements())); | 12609 Handle<FixedArray> elements(FixedArray::cast(object->elements())); |
12590 bool is_arguments = | 12610 bool is_arguments = |
12591 (elements->map() == isolate->heap()->sloppy_arguments_elements_map()); | 12611 (elements->map() == isolate->heap()->sloppy_arguments_elements_map()); |
12592 | 12612 |
12593 DCHECK(object->HasDictionaryElements() || | 12613 DCHECK(object->HasDictionaryElements() || |
12594 object->HasDictionaryArgumentsElements()); | 12614 object->HasDictionaryArgumentsElements()); |
12595 | 12615 |
12596 Handle<SeededNumberDictionary> dictionary(is_arguments | 12616 Handle<SeededNumberDictionary> dictionary(is_arguments |
12597 ? SeededNumberDictionary::cast(elements->get(1)) | 12617 ? SeededNumberDictionary::cast(elements->get(1)) |
12598 : SeededNumberDictionary::cast(*elements)); | 12618 : SeededNumberDictionary::cast(*elements)); |
12599 | 12619 |
12600 int entry = dictionary->FindEntry(index); | 12620 int entry = dictionary->FindEntry(index); |
12601 if (entry != SeededNumberDictionary::kNotFound) { | 12621 DCHECK_NE(SeededNumberDictionary::kNotFound, entry); |
| 12622 |
| 12623 PropertyDetails details = dictionary->DetailsAt(entry); |
| 12624 details = PropertyDetails(attributes, DATA, details.dictionary_index(), |
| 12625 PropertyCellType::kNoCell); |
| 12626 dictionary->DetailsAtPut(entry, details); |
| 12627 |
| 12628 // Elements of the arguments object in slow mode might be slow aliases. |
| 12629 if (is_arguments) { |
12602 Handle<Object> element(dictionary->ValueAt(entry), isolate); | 12630 Handle<Object> element(dictionary->ValueAt(entry), isolate); |
12603 PropertyDetails details = dictionary->DetailsAt(entry); | 12631 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 = | 12632 Handle<AliasedArgumentsEntry> entry = |
12615 Handle<AliasedArgumentsEntry>::cast(element); | 12633 Handle<AliasedArgumentsEntry>::cast(element); |
12616 Handle<Context> context(Context::cast(elements->get(0))); | 12634 Handle<Context> context(Context::cast(elements->get(0))); |
12617 int context_index = entry->aliased_context_slot(); | 12635 int context_index = entry->aliased_context_slot(); |
12618 DCHECK(!context->get(context_index)->IsTheHole()); | 12636 DCHECK(!context->get(context_index)->IsTheHole()); |
12619 context->set(context_index, *value); | 12637 context->set(context_index, *value); |
12620 // For elements that are still writable we keep slow aliasing. | 12638 // For elements that are still writable we keep slow aliasing. |
12621 if (!details.IsReadOnly()) value = element; | 12639 if (!details.IsReadOnly()) value = element; |
12622 } | 12640 } |
12623 dictionary->ValueAtPut(entry, *value); | 12641 } |
12624 } else { | 12642 |
12625 DCHECK(object->map()->is_extensible()); | 12643 dictionary->ValueAtPut(entry, *value); |
12626 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | 12644 } |
12627 Handle<SeededNumberDictionary> new_dictionary = | 12645 |
12628 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, | 12646 |
12629 details); | 12647 void JSObject::AddDictionaryElement(Handle<JSObject> object, uint32_t index, |
12630 if (*dictionary != *new_dictionary) { | 12648 Handle<Object> value, |
12631 if (is_arguments) { | 12649 PropertyAttributes attributes) { |
12632 elements->set(1, *new_dictionary); | 12650 // TODO(verwaest): Handle with the elements accessor. |
12633 } else { | 12651 Isolate* isolate = object->GetIsolate(); |
12634 object->set_elements(*new_dictionary); | 12652 |
12635 } | 12653 // Insert element in the dictionary. |
12636 dictionary = new_dictionary; | 12654 Handle<FixedArray> elements(FixedArray::cast(object->elements())); |
| 12655 bool is_arguments = |
| 12656 (elements->map() == isolate->heap()->sloppy_arguments_elements_map()); |
| 12657 |
| 12658 DCHECK(object->HasDictionaryElements() || |
| 12659 object->HasDictionaryArgumentsElements()); |
| 12660 |
| 12661 Handle<SeededNumberDictionary> dictionary( |
| 12662 is_arguments ? SeededNumberDictionary::cast(elements->get(1)) |
| 12663 : SeededNumberDictionary::cast(*elements)); |
| 12664 |
| 12665 #ifdef DEBUG |
| 12666 int entry = dictionary->FindEntry(index); |
| 12667 DCHECK_EQ(SeededNumberDictionary::kNotFound, entry); |
| 12668 DCHECK(object->map()->is_extensible()); |
| 12669 #endif |
| 12670 |
| 12671 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
| 12672 Handle<SeededNumberDictionary> new_dictionary = |
| 12673 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, details); |
| 12674 if (*dictionary != *new_dictionary) { |
| 12675 if (is_arguments) { |
| 12676 elements->set(1, *new_dictionary); |
| 12677 } else { |
| 12678 object->set_elements(*new_dictionary); |
12637 } | 12679 } |
| 12680 dictionary = new_dictionary; |
12638 } | 12681 } |
12639 | 12682 |
12640 // Update the array length if this JSObject is an array. | 12683 // Update the array length if this JSObject is an array. |
12641 if (object->IsJSArray()) { | 12684 if (object->IsJSArray()) { |
12642 JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index, | 12685 JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index, |
12643 value); | 12686 value); |
12644 } | 12687 } |
12645 | 12688 |
12646 // Attempt to put this object back in fast case. | 12689 // Attempt to put this object back in fast case. |
12647 if (object->ShouldConvertToFastElements()) { | 12690 if (object->ShouldConvertToFastElements()) { |
(...skipping 20 matching lines...) Expand all Loading... |
12668 #ifdef DEBUG | 12711 #ifdef DEBUG |
12669 if (FLAG_trace_normalization) { | 12712 if (FLAG_trace_normalization) { |
12670 OFStream os(stdout); | 12713 OFStream os(stdout); |
12671 os << "Object elements are fast case again:\n"; | 12714 os << "Object elements are fast case again:\n"; |
12672 object->Print(os); | 12715 object->Print(os); |
12673 } | 12716 } |
12674 #endif | 12717 #endif |
12675 } | 12718 } |
12676 } | 12719 } |
12677 | 12720 |
12678 void JSObject::SetFastDoubleElement(Handle<JSObject> object, uint32_t index, | 12721 |
| 12722 void JSObject::AddFastDoubleElement(Handle<JSObject> object, uint32_t index, |
12679 Handle<Object> value) { | 12723 Handle<Object> value) { |
12680 DCHECK(object->HasFastDoubleElements()); | 12724 DCHECK(object->HasFastDoubleElements()); |
12681 | 12725 |
12682 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements())); | 12726 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements())); |
12683 uint32_t elms_length = static_cast<uint32_t>(base_elms->length()); | 12727 uint32_t elms_length = static_cast<uint32_t>(base_elms->length()); |
12684 uint32_t length = elms_length; | 12728 uint32_t length = elms_length; |
12685 | 12729 |
12686 bool introduces_holes = true; | 12730 bool introduces_holes = true; |
12687 if (object->IsJSArray()) { | 12731 if (object->IsJSArray()) { |
12688 // In case of JSArray, the length does not equal the capacity. | 12732 // In case of JSArray, the length does not equal the capacity. |
12689 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(&length)); | 12733 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(&length)); |
12690 introduces_holes = index > length; | 12734 introduces_holes = index > length; |
12691 } else { | 12735 } else { |
12692 introduces_holes = index >= elms_length; | 12736 introduces_holes = index >= elms_length; |
12693 } | 12737 } |
12694 | 12738 |
12695 // If the value object is not a heap number, switch to fast elements and try | 12739 // If the value object is not a heap number, switch to fast elements and try |
12696 // again. | 12740 // again. |
12697 if (!value->IsNumber()) { | 12741 if (!value->IsNumber()) { |
12698 SetFastElementsCapacityAndLength(object, elms_length, length, | 12742 SetFastElementsCapacityAndLength(object, elms_length, length, |
12699 kDontAllowSmiElements); | 12743 kDontAllowSmiElements); |
12700 SetFastElement(object, index, value); | 12744 AddFastElement(object, index, value); |
12701 return; | 12745 return; |
12702 } | 12746 } |
12703 | 12747 |
12704 // If the array is growing, and it's not growth by a single element at the | 12748 // 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. | 12749 // end, make sure that the ElementsKind is HOLEY. |
12706 ElementsKind elements_kind = object->GetElementsKind(); | 12750 if (introduces_holes && !IsFastHoleyElementsKind(object->GetElementsKind())) { |
12707 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) { | 12751 ElementsKind transitioned_kind = FAST_HOLEY_DOUBLE_ELEMENTS; |
12708 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); | |
12709 TransitionElementsKind(object, transitioned_kind); | 12752 TransitionElementsKind(object, transitioned_kind); |
12710 } | 12753 } |
12711 | 12754 |
12712 // Check whether there is extra space in the fixed array. | 12755 // Check whether there is extra space in the fixed array. |
12713 if (index < elms_length) { | 12756 if (index < elms_length) { |
12714 Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements())); | 12757 Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements())); |
12715 elms->set(index, value->Number()); | 12758 elms->set(index, value->Number()); |
12716 if (object->IsJSArray()) { | 12759 if (object->IsJSArray()) { |
12717 // Update the length of the array if needed. | 12760 // Update the length of the array if needed. |
12718 uint32_t array_length = 0; | 12761 uint32_t array_length = 0; |
(...skipping 20 matching lines...) Expand all Loading... |
12739 } | 12782 } |
12740 | 12783 |
12741 // Otherwise default to slow case. | 12784 // Otherwise default to slow case. |
12742 DCHECK(object->HasFastDoubleElements()); | 12785 DCHECK(object->HasFastDoubleElements()); |
12743 DCHECK(object->map()->has_fast_double_elements()); | 12786 DCHECK(object->map()->has_fast_double_elements()); |
12744 DCHECK(object->elements()->IsFixedDoubleArray() || | 12787 DCHECK(object->elements()->IsFixedDoubleArray() || |
12745 object->elements()->length() == 0); | 12788 object->elements()->length() == 0); |
12746 | 12789 |
12747 NormalizeElements(object); | 12790 NormalizeElements(object); |
12748 DCHECK(object->HasDictionaryElements()); | 12791 DCHECK(object->HasDictionaryElements()); |
12749 SetDictionaryElement(object, index, value, NONE); | 12792 AddDictionaryElement(object, index, value, NONE); |
12750 } | 12793 } |
12751 | 12794 |
12752 | 12795 |
12753 // static | 12796 // static |
12754 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, | 12797 MaybeHandle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, |
12755 uint32_t index, Handle<Object> value, | 12798 uint32_t index, Handle<Object> value, |
12756 LanguageMode language_mode) { | 12799 LanguageMode language_mode) { |
12757 Isolate* isolate = object->GetIsolate(); | 12800 Isolate* isolate = object->GetIsolate(); |
12758 LookupIterator it(isolate, object, index); | 12801 LookupIterator it(isolate, object, index); |
12759 return SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED); | 12802 return SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED); |
(...skipping 21 matching lines...) Expand all Loading... |
12781 d->set_requires_slow_elements(); | 12824 d->set_requires_slow_elements(); |
12782 } | 12825 } |
12783 | 12826 |
12784 Handle<Object> result = value; | 12827 Handle<Object> result = value; |
12785 | 12828 |
12786 switch (receiver->GetElementsKind()) { | 12829 switch (receiver->GetElementsKind()) { |
12787 case FAST_SMI_ELEMENTS: | 12830 case FAST_SMI_ELEMENTS: |
12788 case FAST_ELEMENTS: | 12831 case FAST_ELEMENTS: |
12789 case FAST_HOLEY_SMI_ELEMENTS: | 12832 case FAST_HOLEY_SMI_ELEMENTS: |
12790 case FAST_HOLEY_ELEMENTS: | 12833 case FAST_HOLEY_ELEMENTS: |
12791 SetFastElement(receiver, index, value); | 12834 AddFastElement(receiver, index, value); |
12792 break; | 12835 break; |
12793 case FAST_DOUBLE_ELEMENTS: | 12836 case FAST_DOUBLE_ELEMENTS: |
12794 case FAST_HOLEY_DOUBLE_ELEMENTS: | 12837 case FAST_HOLEY_DOUBLE_ELEMENTS: |
12795 SetFastDoubleElement(receiver, index, value); | 12838 AddFastDoubleElement(receiver, index, value); |
12796 break; | 12839 break; |
12797 | 12840 |
12798 case DICTIONARY_ELEMENTS: | 12841 case DICTIONARY_ELEMENTS: |
12799 SetDictionaryElement(receiver, index, value, attributes); | 12842 AddDictionaryElement(receiver, index, value, attributes); |
12800 break; | 12843 break; |
12801 case SLOPPY_ARGUMENTS_ELEMENTS: | 12844 case SLOPPY_ARGUMENTS_ELEMENTS: |
12802 SetSloppyArgumentsElement(receiver, index, value, attributes); | 12845 AddSloppyArgumentsElement(receiver, index, value, attributes); |
12803 break; | 12846 break; |
12804 | 12847 |
12805 // Elements cannot be added to typed arrays. | 12848 // Elements cannot be added to typed arrays. |
12806 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 12849 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
12807 case EXTERNAL_##TYPE##_ELEMENTS: \ | 12850 case EXTERNAL_##TYPE##_ELEMENTS: \ |
12808 case TYPE##_ELEMENTS: | 12851 case TYPE##_ELEMENTS: |
12809 | 12852 |
12810 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 12853 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
12811 | 12854 |
12812 #undef TYPED_ARRAY_CASE | 12855 #undef TYPED_ARRAY_CASE |
(...skipping 3849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16662 Handle<Object> new_value) { | 16705 Handle<Object> new_value) { |
16663 if (cell->value() != *new_value) { | 16706 if (cell->value() != *new_value) { |
16664 cell->set_value(*new_value); | 16707 cell->set_value(*new_value); |
16665 Isolate* isolate = cell->GetIsolate(); | 16708 Isolate* isolate = cell->GetIsolate(); |
16666 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16709 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
16667 isolate, DependentCode::kPropertyCellChangedGroup); | 16710 isolate, DependentCode::kPropertyCellChangedGroup); |
16668 } | 16711 } |
16669 } | 16712 } |
16670 } // namespace internal | 16713 } // namespace internal |
16671 } // namespace v8 | 16714 } // namespace v8 |
OLD | NEW |