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 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 auto curr = PrototypeIterator::GetCurrent(iter); | 599 auto curr = PrototypeIterator::GetCurrent(iter); |
600 if (!curr->IsJSObject()) break; | 600 if (!curr->IsJSObject()) break; |
601 auto obj = Handle<JSObject>::cast(curr); | 601 auto obj = Handle<JSObject>::cast(curr); |
602 if (!obj->HasIndexedInterceptor()) continue; | 602 if (!obj->HasIndexedInterceptor()) continue; |
603 if (obj->GetIndexedInterceptor()->all_can_read()) return obj; | 603 if (obj->GetIndexedInterceptor()->all_can_read()) return obj; |
604 } | 604 } |
605 return MaybeHandle<JSObject>(); | 605 return MaybeHandle<JSObject>(); |
606 } | 606 } |
607 | 607 |
608 | 608 |
609 MaybeHandle<Object> JSObject::GetElementWithFailedAccessCheck( | |
610 Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver, | |
611 uint32_t index) { | |
612 Handle<JSObject> holder = object; | |
613 PrototypeIterator::WhereToStart where_to_start = | |
614 PrototypeIterator::START_AT_RECEIVER; | |
615 while (true) { | |
616 auto all_can_read_holder = | |
617 FindIndexedAllCanReadHolder(isolate, holder, where_to_start); | |
618 if (!all_can_read_holder.ToHandle(&holder)) break; | |
619 auto result = | |
620 JSObject::GetElementWithInterceptor(holder, receiver, index, false); | |
621 if (isolate->has_scheduled_exception()) break; | |
622 if (!result.is_null()) return result; | |
623 where_to_start = PrototypeIterator::START_AT_PROTOTYPE; | |
624 } | |
625 isolate->ReportFailedAccessCheck(object); | |
626 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
627 return isolate->factory()->undefined_value(); | |
628 } | |
629 | |
630 | |
631 Maybe<PropertyAttributes> JSObject::GetElementAttributesWithFailedAccessCheck( | 609 Maybe<PropertyAttributes> JSObject::GetElementAttributesWithFailedAccessCheck( |
632 Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver, | 610 Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver, |
633 uint32_t index) { | 611 uint32_t index) { |
634 Handle<JSObject> holder = object; | 612 Handle<JSObject> holder = object; |
635 PrototypeIterator::WhereToStart where_to_start = | 613 PrototypeIterator::WhereToStart where_to_start = |
636 PrototypeIterator::START_AT_RECEIVER; | 614 PrototypeIterator::START_AT_RECEIVER; |
637 while (true) { | 615 while (true) { |
638 auto all_can_read_holder = | 616 auto all_can_read_holder = |
639 FindIndexedAllCanReadHolder(isolate, holder, where_to_start); | 617 FindIndexedAllCanReadHolder(isolate, holder, where_to_start); |
640 if (!all_can_read_holder.ToHandle(&holder)) break; | 618 if (!all_can_read_holder.ToHandle(&holder)) break; |
641 auto result = | 619 auto result = |
642 JSObject::GetElementAttributeFromInterceptor(holder, receiver, index); | 620 JSObject::GetElementAttributeFromInterceptor(holder, receiver, index); |
643 if (isolate->has_scheduled_exception()) break; | 621 if (isolate->has_scheduled_exception()) break; |
644 if (result.IsJust() && result.FromJust() != ABSENT) return result; | 622 if (result.IsJust() && result.FromJust() != ABSENT) return result; |
645 where_to_start = PrototypeIterator::START_AT_PROTOTYPE; | 623 where_to_start = PrototypeIterator::START_AT_PROTOTYPE; |
646 } | 624 } |
647 isolate->ReportFailedAccessCheck(object); | 625 isolate->ReportFailedAccessCheck(object); |
648 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>()); | 626 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>()); |
649 return Just(ABSENT); | 627 return Just(ABSENT); |
650 } | 628 } |
651 | 629 |
652 | 630 |
653 MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate, | |
654 Handle<Object> object, | |
655 Handle<Object> receiver, | |
656 uint32_t index) { | |
657 DCHECK(!object->IsUndefined()); | |
658 | |
659 // Iterate up the prototype chain until an element is found or the null | |
660 // prototype is encountered. | |
661 for (PrototypeIterator iter(isolate, object, | |
662 object->IsJSProxy() || object->IsJSObject() | |
663 ? PrototypeIterator::START_AT_RECEIVER | |
664 : PrototypeIterator::START_AT_PROTOTYPE); | |
665 !iter.IsAtEnd(); iter.Advance()) { | |
666 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | |
667 return JSProxy::GetElementWithHandler( | |
668 Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver, | |
669 index); | |
670 } | |
671 | |
672 // Inline the case for JSObjects. Doing so significantly improves the | |
673 // performance of fetching elements where checking the prototype chain is | |
674 // necessary. | |
675 Handle<JSObject> js_object = | |
676 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | |
677 | |
678 // Check access rights if needed. | |
679 if (js_object->IsAccessCheckNeeded()) { | |
680 if (!isolate->MayAccess(js_object)) { | |
681 return JSObject::GetElementWithFailedAccessCheck(isolate, js_object, | |
682 receiver, index); | |
683 } | |
684 } | |
685 | |
686 if (js_object->HasIndexedInterceptor()) { | |
687 return JSObject::GetElementWithInterceptor(js_object, receiver, index, | |
688 true); | |
689 } | |
690 | |
691 if (js_object->elements() != isolate->heap()->empty_fixed_array()) { | |
692 Handle<Object> result; | |
693 ASSIGN_RETURN_ON_EXCEPTION( | |
694 isolate, result, | |
695 js_object->GetElementsAccessor()->Get(receiver, js_object, index), | |
696 Object); | |
697 if (!result->IsTheHole()) return result; | |
698 } | |
699 } | |
700 | |
701 return isolate->factory()->undefined_value(); | |
702 } | |
703 | |
704 | |
705 MaybeHandle<Object> Object::SetElementWithReceiver( | 631 MaybeHandle<Object> Object::SetElementWithReceiver( |
706 Isolate* isolate, Handle<Object> object, Handle<Object> receiver, | 632 Isolate* isolate, Handle<Object> object, Handle<Object> receiver, |
707 uint32_t index, Handle<Object> value, LanguageMode language_mode) { | 633 uint32_t index, Handle<Object> value, LanguageMode language_mode) { |
708 // Iterate up the prototype chain until an element is found or the null | 634 // Iterate up the prototype chain until an element is found or the null |
709 // prototype is encountered. | 635 // prototype is encountered. |
710 bool done = false; | 636 bool done = false; |
711 for (PrototypeIterator iter(isolate, object, | 637 for (PrototypeIterator iter(isolate, object, |
712 object->IsJSProxy() || object->IsJSObject() | 638 object->IsJSProxy() || object->IsJSObject() |
713 ? PrototypeIterator::START_AT_RECEIVER | 639 ? PrototypeIterator::START_AT_RECEIVER |
714 : PrototypeIterator::START_AT_PROTOTYPE); | 640 : PrototypeIterator::START_AT_PROTOTYPE); |
(...skipping 7493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8208 GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( | 8134 GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( |
8209 this, length() - new_length); | 8135 this, length() - new_length); |
8210 } | 8136 } |
8211 } | 8137 } |
8212 | 8138 |
8213 | 8139 |
8214 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike( | 8140 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike( |
8215 Handle<FixedArray> content, Handle<JSObject> array, KeyFilter filter) { | 8141 Handle<FixedArray> content, Handle<JSObject> array, KeyFilter filter) { |
8216 DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements()); | 8142 DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements()); |
8217 ElementsAccessor* accessor = array->GetElementsAccessor(); | 8143 ElementsAccessor* accessor = array->GetElementsAccessor(); |
8218 Handle<FixedArray> result; | 8144 Handle<FixedArray> result = |
8219 ASSIGN_RETURN_ON_EXCEPTION( | 8145 accessor->AddElementsToFixedArray(array, content, filter); |
8220 array->GetIsolate(), result, | |
8221 accessor->AddElementsToFixedArray(array, content, filter), FixedArray); | |
8222 | 8146 |
8223 #ifdef ENABLE_SLOW_DCHECKS | 8147 #ifdef ENABLE_SLOW_DCHECKS |
8224 if (FLAG_enable_slow_asserts) { | 8148 if (FLAG_enable_slow_asserts) { |
8225 DisallowHeapAllocation no_allocation; | 8149 DisallowHeapAllocation no_allocation; |
8226 for (int i = 0; i < result->length(); i++) { | 8150 for (int i = 0; i < result->length(); i++) { |
8227 Object* current = result->get(i); | 8151 Object* current = result->get(i); |
8228 DCHECK(current->IsNumber() || current->IsName()); | 8152 DCHECK(current->IsNumber() || current->IsName()); |
8229 } | 8153 } |
8230 } | 8154 } |
8231 #endif | 8155 #endif |
(...skipping 4005 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12237 DCHECK(array->AllowsSetElementsLength()); | 12161 DCHECK(array->AllowsSetElementsLength()); |
12238 if (!array->map()->is_observed()) { | 12162 if (!array->map()->is_observed()) { |
12239 return array->GetElementsAccessor()->SetLength(array, new_length_handle); | 12163 return array->GetElementsAccessor()->SetLength(array, new_length_handle); |
12240 } | 12164 } |
12241 | 12165 |
12242 Isolate* isolate = array->GetIsolate(); | 12166 Isolate* isolate = array->GetIsolate(); |
12243 List<uint32_t> indices; | 12167 List<uint32_t> indices; |
12244 List<Handle<Object> > old_values; | 12168 List<Handle<Object> > old_values; |
12245 Handle<Object> old_length_handle(array->length(), isolate); | 12169 Handle<Object> old_length_handle(array->length(), isolate); |
12246 uint32_t old_length = 0; | 12170 uint32_t old_length = 0; |
12247 CHECK(old_length_handle->ToArrayIndex(&old_length)); | 12171 CHECK(old_length_handle->ToArrayLength(&old_length)); |
12248 uint32_t new_length = 0; | 12172 uint32_t new_length = 0; |
12249 CHECK(new_length_handle->ToArrayIndex(&new_length)); | 12173 CHECK(new_length_handle->ToArrayLength(&new_length)); |
12250 | 12174 |
12251 static const PropertyAttributes kNoAttrFilter = NONE; | 12175 static const PropertyAttributes kNoAttrFilter = NONE; |
12252 int num_elements = array->NumberOfOwnElements(kNoAttrFilter); | 12176 int num_elements = array->NumberOfOwnElements(kNoAttrFilter); |
12253 if (num_elements > 0) { | 12177 if (num_elements > 0) { |
12254 if (old_length == static_cast<uint32_t>(num_elements)) { | 12178 if (old_length == static_cast<uint32_t>(num_elements)) { |
12255 // Simple case for arrays without holes. | 12179 // Simple case for arrays without holes. |
12256 for (uint32_t i = old_length - 1; i + 1 > new_length; --i) { | 12180 for (uint32_t i = old_length - 1; i + 1 > new_length; --i) { |
12257 if (!GetOldValue(isolate, array, i, &old_values, &indices)) break; | 12181 if (!GetOldValue(isolate, array, i, &old_values, &indices)) break; |
12258 } | 12182 } |
12259 } else { | 12183 } else { |
12260 // For sparse arrays, only iterate over existing elements. | 12184 // For sparse arrays, only iterate over existing elements. |
12261 // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over | 12185 // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over |
12262 // the to-be-removed indices twice. | 12186 // the to-be-removed indices twice. |
12263 Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements); | 12187 Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements); |
12264 array->GetOwnElementKeys(*keys, kNoAttrFilter); | 12188 array->GetOwnElementKeys(*keys, kNoAttrFilter); |
12265 while (num_elements-- > 0) { | 12189 while (num_elements-- > 0) { |
12266 uint32_t index = NumberToUint32(keys->get(num_elements)); | 12190 uint32_t index = NumberToUint32(keys->get(num_elements)); |
12267 if (index < new_length) break; | 12191 if (index < new_length) break; |
12268 if (!GetOldValue(isolate, array, index, &old_values, &indices)) break; | 12192 if (!GetOldValue(isolate, array, index, &old_values, &indices)) break; |
12269 } | 12193 } |
12270 } | 12194 } |
12271 } | 12195 } |
12272 | 12196 |
12273 Handle<Object> hresult; | 12197 Handle<Object> hresult; |
12274 ASSIGN_RETURN_ON_EXCEPTION( | 12198 ASSIGN_RETURN_ON_EXCEPTION( |
12275 isolate, hresult, | 12199 isolate, hresult, |
12276 array->GetElementsAccessor()->SetLength(array, new_length_handle), | 12200 array->GetElementsAccessor()->SetLength(array, new_length_handle), |
12277 Object); | 12201 Object); |
12278 | 12202 |
12279 CHECK(array->length()->ToArrayIndex(&new_length)); | 12203 CHECK(array->length()->ToArrayLength(&new_length)); |
12280 if (old_length == new_length) return hresult; | 12204 if (old_length == new_length) return hresult; |
12281 | 12205 |
12282 RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object); | 12206 RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object); |
12283 | 12207 |
12284 for (int i = 0; i < indices.length(); ++i) { | 12208 for (int i = 0; i < indices.length(); ++i) { |
12285 // For deletions where the property was an accessor, old_values[i] | 12209 // For deletions where the property was an accessor, old_values[i] |
12286 // will be the hole, which instructs EnqueueChangeRecord to elide | 12210 // will be the hole, which instructs EnqueueChangeRecord to elide |
12287 // the "oldValue" property. | 12211 // the "oldValue" property. |
12288 RETURN_ON_EXCEPTION( | 12212 RETURN_ON_EXCEPTION( |
12289 isolate, | 12213 isolate, |
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12758 args.Call(setter, index, v8::Utils::ToLocal(value)); | 12682 args.Call(setter, index, v8::Utils::ToLocal(value)); |
12759 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 12683 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
12760 if (!result.IsEmpty()) return value; | 12684 if (!result.IsEmpty()) return value; |
12761 } | 12685 } |
12762 | 12686 |
12763 return SetElementWithoutInterceptor(object, index, value, attributes, | 12687 return SetElementWithoutInterceptor(object, index, value, attributes, |
12764 language_mode, check_prototype, set_mode); | 12688 language_mode, check_prototype, set_mode); |
12765 } | 12689 } |
12766 | 12690 |
12767 | 12691 |
12768 MaybeHandle<Object> JSObject::GetElementWithCallback( | |
12769 Handle<JSObject> object, | |
12770 Handle<Object> receiver, | |
12771 Handle<Object> structure, | |
12772 uint32_t index, | |
12773 Handle<Object> holder) { | |
12774 Isolate* isolate = object->GetIsolate(); | |
12775 DCHECK(!structure->IsForeign()); | |
12776 // api style callbacks. | |
12777 if (structure->IsExecutableAccessorInfo()) { | |
12778 Handle<ExecutableAccessorInfo> data = | |
12779 Handle<ExecutableAccessorInfo>::cast(structure); | |
12780 Object* fun_obj = data->getter(); | |
12781 v8::AccessorNameGetterCallback call_fun = | |
12782 v8::ToCData<v8::AccessorNameGetterCallback>(fun_obj); | |
12783 if (call_fun == NULL) return isolate->factory()->undefined_value(); | |
12784 Handle<JSObject> holder_handle = Handle<JSObject>::cast(holder); | |
12785 Handle<String> key = isolate->factory()->Uint32ToString(index); | |
12786 LOG(isolate, ApiNamedPropertyAccess("load", *holder_handle, *key)); | |
12787 PropertyCallbackArguments | |
12788 args(isolate, data->data(), *receiver, *holder_handle); | |
12789 v8::Handle<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(key)); | |
12790 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
12791 if (result.IsEmpty()) return isolate->factory()->undefined_value(); | |
12792 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | |
12793 result_internal->VerifyApiCallResultType(); | |
12794 // Rebox handle before return. | |
12795 return handle(*result_internal, isolate); | |
12796 } | |
12797 | |
12798 // __defineGetter__ callback | |
12799 if (structure->IsAccessorPair()) { | |
12800 Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(), | |
12801 isolate); | |
12802 if (getter->IsSpecFunction()) { | |
12803 // TODO(rossberg): nicer would be to cast to some JSCallable here... | |
12804 return GetPropertyWithDefinedGetter( | |
12805 receiver, Handle<JSReceiver>::cast(getter)); | |
12806 } | |
12807 // Getter is not a function. | |
12808 return isolate->factory()->undefined_value(); | |
12809 } | |
12810 | |
12811 UNREACHABLE(); | |
12812 return MaybeHandle<Object>(); | |
12813 } | |
12814 | |
12815 | |
12816 MaybeHandle<Object> JSObject::SetElementWithCallback( | 12692 MaybeHandle<Object> JSObject::SetElementWithCallback( |
12817 Handle<Object> object, Handle<Object> structure, uint32_t index, | 12693 Handle<Object> object, Handle<Object> structure, uint32_t index, |
12818 Handle<Object> value, Handle<JSObject> holder, LanguageMode language_mode) { | 12694 Handle<Object> value, Handle<JSObject> holder, LanguageMode language_mode) { |
12819 Isolate* isolate = holder->GetIsolate(); | 12695 Isolate* isolate = holder->GetIsolate(); |
12820 | 12696 |
12821 // We should never get here to initialize a const with the hole | 12697 // We should never get here to initialize a const with the hole |
12822 // value since a const declaration would conflict with the setter. | 12698 // value since a const declaration would conflict with the setter. |
12823 DCHECK(!value->IsTheHole()); | 12699 DCHECK(!value->IsTheHole()); |
12824 DCHECK(!structure->IsForeign()); | 12700 DCHECK(!structure->IsForeign()); |
12825 if (structure->IsExecutableAccessorInfo()) { | 12701 if (structure->IsExecutableAccessorInfo()) { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12920 object, index, value, &found, language_mode); | 12796 object, index, value, &found, language_mode); |
12921 if (found) return result; | 12797 if (found) return result; |
12922 } | 12798 } |
12923 | 12799 |
12924 uint32_t new_capacity = capacity; | 12800 uint32_t new_capacity = capacity; |
12925 // Check if the length property of this object needs to be updated. | 12801 // Check if the length property of this object needs to be updated. |
12926 uint32_t array_length = 0; | 12802 uint32_t array_length = 0; |
12927 bool must_update_array_length = false; | 12803 bool must_update_array_length = false; |
12928 bool introduces_holes = true; | 12804 bool introduces_holes = true; |
12929 if (object->IsJSArray()) { | 12805 if (object->IsJSArray()) { |
12930 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length)); | 12806 CHECK( |
| 12807 Handle<JSArray>::cast(object)->length()->ToArrayLength(&array_length)); |
12931 introduces_holes = index > array_length; | 12808 introduces_holes = index > array_length; |
12932 if (index >= array_length) { | 12809 if (index >= array_length) { |
12933 must_update_array_length = true; | 12810 must_update_array_length = true; |
12934 array_length = index + 1; | 12811 array_length = index + 1; |
12935 } | 12812 } |
12936 } else { | 12813 } else { |
12937 introduces_holes = index >= capacity; | 12814 introduces_holes = index >= capacity; |
12938 } | 12815 } |
12939 | 12816 |
12940 // If the array is growing, and it's not growth by a single element at the | 12817 // If the array is growing, and it's not growth by a single element at the |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13115 // Update the array length if this JSObject is an array. | 12992 // Update the array length if this JSObject is an array. |
13116 if (object->IsJSArray()) { | 12993 if (object->IsJSArray()) { |
13117 JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index, | 12994 JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index, |
13118 value); | 12995 value); |
13119 } | 12996 } |
13120 | 12997 |
13121 // Attempt to put this object back in fast case. | 12998 // Attempt to put this object back in fast case. |
13122 if (object->ShouldConvertToFastElements()) { | 12999 if (object->ShouldConvertToFastElements()) { |
13123 uint32_t new_length = 0; | 13000 uint32_t new_length = 0; |
13124 if (object->IsJSArray()) { | 13001 if (object->IsJSArray()) { |
13125 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&new_length)); | 13002 CHECK( |
| 13003 Handle<JSArray>::cast(object)->length()->ToArrayLength(&new_length)); |
13126 } else { | 13004 } else { |
13127 new_length = dictionary->max_number_key() + 1; | 13005 new_length = dictionary->max_number_key() + 1; |
13128 } | 13006 } |
13129 bool has_smi_only_elements = false; | 13007 bool has_smi_only_elements = false; |
13130 bool should_convert_to_fast_double_elements = | 13008 bool should_convert_to_fast_double_elements = |
13131 object->ShouldConvertToFastDoubleElements(&has_smi_only_elements); | 13009 object->ShouldConvertToFastDoubleElements(&has_smi_only_elements); |
13132 SetFastElementsCapacitySmiMode smi_mode = | 13010 SetFastElementsCapacitySmiMode smi_mode = |
13133 has_smi_only_elements ? kForceSmiElements : kAllowSmiElements; | 13011 has_smi_only_elements ? kForceSmiElements : kAllowSmiElements; |
13134 | 13012 |
13135 if (should_convert_to_fast_double_elements) { | 13013 if (should_convert_to_fast_double_elements) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13170 object, index, value, &found, language_mode); | 13048 object, index, value, &found, language_mode); |
13171 if (found) return result; | 13049 if (found) return result; |
13172 } | 13050 } |
13173 | 13051 |
13174 // If the value object is not a heap number, switch to fast elements and try | 13052 // If the value object is not a heap number, switch to fast elements and try |
13175 // again. | 13053 // again. |
13176 bool value_is_smi = value->IsSmi(); | 13054 bool value_is_smi = value->IsSmi(); |
13177 bool introduces_holes = true; | 13055 bool introduces_holes = true; |
13178 uint32_t length = elms_length; | 13056 uint32_t length = elms_length; |
13179 if (object->IsJSArray()) { | 13057 if (object->IsJSArray()) { |
13180 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&length)); | 13058 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(&length)); |
13181 introduces_holes = index > length; | 13059 introduces_holes = index > length; |
13182 } else { | 13060 } else { |
13183 introduces_holes = index >= elms_length; | 13061 introduces_holes = index >= elms_length; |
13184 } | 13062 } |
13185 | 13063 |
13186 if (!value->IsNumber()) { | 13064 if (!value->IsNumber()) { |
13187 SetFastElementsCapacityAndLength(object, elms_length, length, | 13065 SetFastElementsCapacityAndLength(object, elms_length, length, |
13188 kDontAllowSmiElements); | 13066 kDontAllowSmiElements); |
13189 Handle<Object> result; | 13067 Handle<Object> result; |
13190 ASSIGN_RETURN_ON_EXCEPTION( | 13068 ASSIGN_RETURN_ON_EXCEPTION( |
(...skipping 16 matching lines...) Expand all Loading... |
13207 TransitionElementsKind(object, transitioned_kind); | 13085 TransitionElementsKind(object, transitioned_kind); |
13208 } | 13086 } |
13209 | 13087 |
13210 // Check whether there is extra space in the fixed array. | 13088 // Check whether there is extra space in the fixed array. |
13211 if (index < elms_length) { | 13089 if (index < elms_length) { |
13212 Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements())); | 13090 Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements())); |
13213 elms->set(index, double_value); | 13091 elms->set(index, double_value); |
13214 if (object->IsJSArray()) { | 13092 if (object->IsJSArray()) { |
13215 // Update the length of the array if needed. | 13093 // Update the length of the array if needed. |
13216 uint32_t array_length = 0; | 13094 uint32_t array_length = 0; |
13217 CHECK( | 13095 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength( |
13218 Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length)); | 13096 &array_length)); |
13219 if (index >= array_length) { | 13097 if (index >= array_length) { |
13220 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1)); | 13098 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1)); |
13221 } | 13099 } |
13222 } | 13100 } |
13223 return value; | 13101 return value; |
13224 } | 13102 } |
13225 | 13103 |
13226 // Allow gap in fast case. | 13104 // Allow gap in fast case. |
13227 if ((index - elms_length) < kMaxGap) { | 13105 if ((index - elms_length) < kMaxGap) { |
13228 // Try allocating extra space. | 13106 // Try allocating extra space. |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13369 PropertyAttributes new_attributes = maybe.FromJust(); | 13247 PropertyAttributes new_attributes = maybe.FromJust(); |
13370 | 13248 |
13371 if (old_attributes == ABSENT) { | 13249 if (old_attributes == ABSENT) { |
13372 if (object->IsJSArray() && | 13250 if (object->IsJSArray() && |
13373 !old_length_handle->SameValue( | 13251 !old_length_handle->SameValue( |
13374 Handle<JSArray>::cast(object)->length())) { | 13252 Handle<JSArray>::cast(object)->length())) { |
13375 new_length_handle = handle(Handle<JSArray>::cast(object)->length(), | 13253 new_length_handle = handle(Handle<JSArray>::cast(object)->length(), |
13376 isolate); | 13254 isolate); |
13377 uint32_t old_length = 0; | 13255 uint32_t old_length = 0; |
13378 uint32_t new_length = 0; | 13256 uint32_t new_length = 0; |
13379 CHECK(old_length_handle->ToArrayIndex(&old_length)); | 13257 CHECK(old_length_handle->ToArrayLength(&old_length)); |
13380 CHECK(new_length_handle->ToArrayIndex(&new_length)); | 13258 CHECK(new_length_handle->ToArrayLength(&new_length)); |
13381 | 13259 |
13382 RETURN_ON_EXCEPTION( | 13260 RETURN_ON_EXCEPTION( |
13383 isolate, BeginPerformSplice(Handle<JSArray>::cast(object)), Object); | 13261 isolate, BeginPerformSplice(Handle<JSArray>::cast(object)), Object); |
13384 RETURN_ON_EXCEPTION( | 13262 RETURN_ON_EXCEPTION( |
13385 isolate, EnqueueChangeRecord(object, "add", name, old_value), Object); | 13263 isolate, EnqueueChangeRecord(object, "add", name, old_value), Object); |
13386 RETURN_ON_EXCEPTION( | 13264 RETURN_ON_EXCEPTION( |
13387 isolate, EnqueueChangeRecord(object, "update", | 13265 isolate, EnqueueChangeRecord(object, "update", |
13388 isolate->factory()->length_string(), | 13266 isolate->factory()->length_string(), |
13389 old_length_handle), | 13267 old_length_handle), |
13390 Object); | 13268 Object); |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13558 handle(JSArray::cast(site->transition_info())); | 13436 handle(JSArray::cast(site->transition_info())); |
13559 ElementsKind kind = transition_info->GetElementsKind(); | 13437 ElementsKind kind = transition_info->GetElementsKind(); |
13560 // if kind is holey ensure that to_kind is as well. | 13438 // if kind is holey ensure that to_kind is as well. |
13561 if (IsHoleyElementsKind(kind)) { | 13439 if (IsHoleyElementsKind(kind)) { |
13562 to_kind = GetHoleyElementsKind(to_kind); | 13440 to_kind = GetHoleyElementsKind(to_kind); |
13563 } | 13441 } |
13564 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { | 13442 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { |
13565 // If the array is huge, it's not likely to be defined in a local | 13443 // If the array is huge, it's not likely to be defined in a local |
13566 // function, so we shouldn't make new instances of it very often. | 13444 // function, so we shouldn't make new instances of it very often. |
13567 uint32_t length = 0; | 13445 uint32_t length = 0; |
13568 CHECK(transition_info->length()->ToArrayIndex(&length)); | 13446 CHECK(transition_info->length()->ToArrayLength(&length)); |
13569 if (length <= kMaximumArrayBytesToPretransition) { | 13447 if (length <= kMaximumArrayBytesToPretransition) { |
13570 if (FLAG_trace_track_allocation_sites) { | 13448 if (FLAG_trace_track_allocation_sites) { |
13571 bool is_nested = site->IsNestedSite(); | 13449 bool is_nested = site->IsNestedSite(); |
13572 PrintF( | 13450 PrintF( |
13573 "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n", | 13451 "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n", |
13574 reinterpret_cast<void*>(*site), | 13452 reinterpret_cast<void*>(*site), |
13575 is_nested ? "(nested)" : "", | 13453 is_nested ? "(nested)" : "", |
13576 ElementsKindToString(kind), | 13454 ElementsKindToString(kind), |
13577 ElementsKindToString(to_kind)); | 13455 ElementsKindToString(to_kind)); |
13578 } | 13456 } |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13672 uint32_t capacity = static_cast<uint32_t>(elms->length()); | 13550 uint32_t capacity = static_cast<uint32_t>(elms->length()); |
13673 uint32_t length = capacity; | 13551 uint32_t length = capacity; |
13674 | 13552 |
13675 if (object->IsJSArray()) { | 13553 if (object->IsJSArray()) { |
13676 Object* raw_length = Handle<JSArray>::cast(object)->length(); | 13554 Object* raw_length = Handle<JSArray>::cast(object)->length(); |
13677 if (raw_length->IsUndefined()) { | 13555 if (raw_length->IsUndefined()) { |
13678 // If length is undefined, then JSArray is being initialized and has no | 13556 // If length is undefined, then JSArray is being initialized and has no |
13679 // elements, assume a length of zero. | 13557 // elements, assume a length of zero. |
13680 length = 0; | 13558 length = 0; |
13681 } else { | 13559 } else { |
13682 CHECK(raw_length->ToArrayIndex(&length)); | 13560 CHECK(raw_length->ToArrayLength(&length)); |
13683 } | 13561 } |
13684 } | 13562 } |
13685 | 13563 |
13686 if (IsFastSmiElementsKind(from_kind) && | 13564 if (IsFastSmiElementsKind(from_kind) && |
13687 IsFastDoubleElementsKind(to_kind)) { | 13565 IsFastDoubleElementsKind(to_kind)) { |
13688 SetFastDoubleElementsCapacityAndLength(object, capacity, length); | 13566 SetFastDoubleElementsCapacityAndLength(object, capacity, length); |
13689 JSObject::ValidateElements(object); | 13567 JSObject::ValidateElements(object); |
13690 return; | 13568 return; |
13691 } | 13569 } |
13692 | 13570 |
(...skipping 22 matching lines...) Expand all Loading... |
13715 // Transitions from HOLEY -> PACKED are not allowed. | 13593 // Transitions from HOLEY -> PACKED are not allowed. |
13716 return !IsFastHoleyElementsKind(from_kind) || | 13594 return !IsFastHoleyElementsKind(from_kind) || |
13717 IsFastHoleyElementsKind(to_kind); | 13595 IsFastHoleyElementsKind(to_kind); |
13718 } | 13596 } |
13719 | 13597 |
13720 | 13598 |
13721 void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array, | 13599 void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array, |
13722 uint32_t index, | 13600 uint32_t index, |
13723 Handle<Object> value) { | 13601 Handle<Object> value) { |
13724 uint32_t old_len = 0; | 13602 uint32_t old_len = 0; |
13725 CHECK(array->length()->ToArrayIndex(&old_len)); | 13603 CHECK(array->length()->ToArrayLength(&old_len)); |
13726 // Check to see if we need to update the length. For now, we make | 13604 // Check to see if we need to update the length. For now, we make |
13727 // sure that the length stays within 32-bits (unsigned). | 13605 // sure that the length stays within 32-bits (unsigned). |
13728 if (index >= old_len && index != 0xffffffff) { | 13606 if (index >= old_len && index != 0xffffffff) { |
13729 Handle<Object> len = array->GetIsolate()->factory()->NewNumber( | 13607 Handle<Object> len = array->GetIsolate()->factory()->NewNumber( |
13730 static_cast<double>(index) + 1); | 13608 static_cast<double>(index) + 1); |
13731 array->set_length(*len); | 13609 array->set_length(*len); |
13732 } | 13610 } |
13733 } | 13611 } |
13734 | 13612 |
13735 | 13613 |
13736 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) { | 13614 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) { |
13737 LookupIterator it(array, array->GetIsolate()->factory()->length_string(), | 13615 LookupIterator it(array, array->GetIsolate()->factory()->length_string(), |
13738 LookupIterator::OWN_SKIP_INTERCEPTOR); | 13616 LookupIterator::OWN_SKIP_INTERCEPTOR); |
13739 CHECK_NE(LookupIterator::ACCESS_CHECK, it.state()); | 13617 CHECK_NE(LookupIterator::ACCESS_CHECK, it.state()); |
13740 CHECK(it.IsFound()); | 13618 CHECK(it.IsFound()); |
13741 CHECK_EQ(LookupIterator::ACCESSOR, it.state()); | 13619 CHECK_EQ(LookupIterator::ACCESSOR, it.state()); |
13742 return it.IsReadOnly(); | 13620 return it.IsReadOnly(); |
13743 } | 13621 } |
13744 | 13622 |
13745 | 13623 |
13746 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array, | 13624 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array, |
13747 uint32_t index) { | 13625 uint32_t index) { |
13748 uint32_t length = 0; | 13626 uint32_t length = 0; |
13749 CHECK(array->length()->ToArrayIndex(&length)); | 13627 CHECK(array->length()->ToArrayLength(&length)); |
13750 if (length <= index) return HasReadOnlyLength(array); | 13628 if (length <= index) return HasReadOnlyLength(array); |
13751 return false; | 13629 return false; |
13752 } | 13630 } |
13753 | 13631 |
13754 | 13632 |
13755 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) { | 13633 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) { |
13756 Isolate* isolate = array->GetIsolate(); | 13634 Isolate* isolate = array->GetIsolate(); |
13757 Handle<Name> length = isolate->factory()->length_string(); | 13635 Handle<Name> length = isolate->factory()->length_string(); |
13758 THROW_NEW_ERROR( | 13636 THROW_NEW_ERROR( |
13759 isolate, | 13637 isolate, |
13760 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, length, array), | 13638 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, length, array), |
13761 Object); | 13639 Object); |
13762 } | 13640 } |
13763 | 13641 |
13764 | 13642 |
13765 MaybeHandle<Object> JSObject::GetElementWithInterceptor(Handle<JSObject> object, | |
13766 Handle<Object> receiver, | |
13767 uint32_t index, | |
13768 bool check_prototype) { | |
13769 Isolate* isolate = object->GetIsolate(); | |
13770 | |
13771 // Make sure that the top context does not change when doing | |
13772 // callbacks or interceptor calls. | |
13773 AssertNoContextChange ncc(isolate); | |
13774 | |
13775 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor(), isolate); | |
13776 if (!interceptor->getter()->IsUndefined()) { | |
13777 v8::IndexedPropertyGetterCallback getter = | |
13778 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); | |
13779 LOG(isolate, | |
13780 ApiIndexedPropertyAccess("interceptor-indexed-get", *object, index)); | |
13781 PropertyCallbackArguments | |
13782 args(isolate, interceptor->data(), *receiver, *object); | |
13783 v8::Handle<v8::Value> result = args.Call(getter, index); | |
13784 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
13785 if (!result.IsEmpty()) { | |
13786 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | |
13787 result_internal->VerifyApiCallResultType(); | |
13788 // Rebox handle before return. | |
13789 return handle(*result_internal, isolate); | |
13790 } | |
13791 } | |
13792 | |
13793 if (!check_prototype) return MaybeHandle<Object>(); | |
13794 | |
13795 ElementsAccessor* handler = object->GetElementsAccessor(); | |
13796 Handle<Object> result; | |
13797 ASSIGN_RETURN_ON_EXCEPTION( | |
13798 isolate, result, handler->Get(receiver, object, index), | |
13799 Object); | |
13800 if (!result->IsTheHole()) return result; | |
13801 | |
13802 PrototypeIterator iter(isolate, object); | |
13803 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); | |
13804 return Object::GetElementWithReceiver( | |
13805 isolate, PrototypeIterator::GetCurrent(iter), receiver, index); | |
13806 } | |
13807 | |
13808 | |
13809 bool JSObject::HasDenseElements() { | 13643 bool JSObject::HasDenseElements() { |
13810 int capacity = 0; | 13644 int capacity = 0; |
13811 int used = 0; | 13645 int used = 0; |
13812 GetElementsCapacityAndUsage(&capacity, &used); | 13646 GetElementsCapacityAndUsage(&capacity, &used); |
13813 return (capacity == 0) || (used > (capacity / 2)); | 13647 return (capacity == 0) || (used > (capacity / 2)); |
13814 } | 13648 } |
13815 | 13649 |
13816 | 13650 |
13817 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { | 13651 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { |
13818 *capacity = 0; | 13652 *capacity = 0; |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13942 dictionary = SeededNumberDictionary::cast(elements); | 13776 dictionary = SeededNumberDictionary::cast(elements); |
13943 } | 13777 } |
13944 // If an element has been added at a very high index in the elements | 13778 // If an element has been added at a very high index in the elements |
13945 // dictionary, we cannot go back to fast case. | 13779 // dictionary, we cannot go back to fast case. |
13946 if (dictionary->requires_slow_elements()) return false; | 13780 if (dictionary->requires_slow_elements()) return false; |
13947 // If the dictionary backing storage takes up roughly half as much | 13781 // If the dictionary backing storage takes up roughly half as much |
13948 // space (in machine words) as a fast-case backing storage would, | 13782 // space (in machine words) as a fast-case backing storage would, |
13949 // the object should have fast elements. | 13783 // the object should have fast elements. |
13950 uint32_t array_size = 0; | 13784 uint32_t array_size = 0; |
13951 if (IsJSArray()) { | 13785 if (IsJSArray()) { |
13952 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size)); | 13786 CHECK(JSArray::cast(this)->length()->ToArrayLength(&array_size)); |
13953 } else { | 13787 } else { |
13954 array_size = dictionary->max_number_key(); | 13788 array_size = dictionary->max_number_key(); |
13955 } | 13789 } |
13956 uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) * | 13790 uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) * |
13957 SeededNumberDictionary::kEntrySize; | 13791 SeededNumberDictionary::kEntrySize; |
13958 return 2 * dictionary_size >= array_size; | 13792 return 2 * dictionary_size >= array_size; |
13959 } | 13793 } |
13960 | 13794 |
13961 | 13795 |
13962 bool JSObject::ShouldConvertToFastDoubleElements( | 13796 bool JSObject::ShouldConvertToFastDoubleElements( |
(...skipping 3365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17328 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell, | 17162 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell, |
17329 Handle<Object> new_value) { | 17163 Handle<Object> new_value) { |
17330 if (cell->value() != *new_value) { | 17164 if (cell->value() != *new_value) { |
17331 cell->set_value(*new_value); | 17165 cell->set_value(*new_value); |
17332 Isolate* isolate = cell->GetIsolate(); | 17166 Isolate* isolate = cell->GetIsolate(); |
17333 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17167 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17334 isolate, DependentCode::kPropertyCellChangedGroup); | 17168 isolate, DependentCode::kPropertyCellChangedGroup); |
17335 } | 17169 } |
17336 } | 17170 } |
17337 } } // namespace v8::internal | 17171 } } // namespace v8::internal |
OLD | NEW |