Chromium Code Reviews| 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 |