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 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 auto curr = PrototypeIterator::GetCurrent(iter); | 604 auto curr = PrototypeIterator::GetCurrent(iter); |
605 if (!curr->IsJSObject()) break; | 605 if (!curr->IsJSObject()) break; |
606 auto obj = Handle<JSObject>::cast(curr); | 606 auto obj = Handle<JSObject>::cast(curr); |
607 if (!obj->HasIndexedInterceptor()) continue; | 607 if (!obj->HasIndexedInterceptor()) continue; |
608 if (obj->GetIndexedInterceptor()->all_can_read()) return obj; | 608 if (obj->GetIndexedInterceptor()->all_can_read()) return obj; |
609 } | 609 } |
610 return MaybeHandle<JSObject>(); | 610 return MaybeHandle<JSObject>(); |
611 } | 611 } |
612 | 612 |
613 | 613 |
614 MaybeHandle<Object> JSObject::GetElementWithFailedAccessCheck( | |
615 Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver, | |
616 uint32_t index) { | |
617 Handle<JSObject> holder = object; | |
618 PrototypeIterator::WhereToStart where_to_start = | |
619 PrototypeIterator::START_AT_RECEIVER; | |
620 while (true) { | |
621 auto all_can_read_holder = | |
622 FindIndexedAllCanReadHolder(isolate, holder, where_to_start); | |
623 if (!all_can_read_holder.ToHandle(&holder)) break; | |
624 auto result = | |
625 JSObject::GetElementWithInterceptor(holder, receiver, index, false); | |
626 if (isolate->has_scheduled_exception()) break; | |
627 if (!result.is_null()) return result; | |
628 where_to_start = PrototypeIterator::START_AT_PROTOTYPE; | |
629 } | |
630 isolate->ReportFailedAccessCheck(object); | |
631 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
632 return isolate->factory()->undefined_value(); | |
633 } | |
634 | |
635 | |
636 Maybe<PropertyAttributes> JSObject::GetElementAttributesWithFailedAccessCheck( | 614 Maybe<PropertyAttributes> JSObject::GetElementAttributesWithFailedAccessCheck( |
637 Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver, | 615 Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver, |
638 uint32_t index) { | 616 uint32_t index) { |
639 Handle<JSObject> holder = object; | 617 Handle<JSObject> holder = object; |
640 PrototypeIterator::WhereToStart where_to_start = | 618 PrototypeIterator::WhereToStart where_to_start = |
641 PrototypeIterator::START_AT_RECEIVER; | 619 PrototypeIterator::START_AT_RECEIVER; |
642 while (true) { | 620 while (true) { |
643 auto all_can_read_holder = | 621 auto all_can_read_holder = |
644 FindIndexedAllCanReadHolder(isolate, holder, where_to_start); | 622 FindIndexedAllCanReadHolder(isolate, holder, where_to_start); |
645 if (!all_can_read_holder.ToHandle(&holder)) break; | 623 if (!all_can_read_holder.ToHandle(&holder)) break; |
646 auto result = | 624 auto result = |
647 JSObject::GetElementAttributeFromInterceptor(holder, receiver, index); | 625 JSObject::GetElementAttributeFromInterceptor(holder, receiver, index); |
648 if (isolate->has_scheduled_exception()) break; | 626 if (isolate->has_scheduled_exception()) break; |
649 if (result.IsJust() && result.FromJust() != ABSENT) return result; | 627 if (result.IsJust() && result.FromJust() != ABSENT) return result; |
650 where_to_start = PrototypeIterator::START_AT_PROTOTYPE; | 628 where_to_start = PrototypeIterator::START_AT_PROTOTYPE; |
651 } | 629 } |
652 isolate->ReportFailedAccessCheck(object); | 630 isolate->ReportFailedAccessCheck(object); |
653 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>()); | 631 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>()); |
654 return Just(ABSENT); | 632 return Just(ABSENT); |
655 } | 633 } |
656 | 634 |
657 | 635 |
658 MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate, | |
659 Handle<Object> object, | |
660 Handle<Object> receiver, | |
661 uint32_t index) { | |
662 DCHECK(!object->IsUndefined()); | |
663 | |
664 // Iterate up the prototype chain until an element is found or the null | |
665 // prototype is encountered. | |
666 for (PrototypeIterator iter(isolate, object, | |
667 object->IsJSProxy() || object->IsJSObject() | |
668 ? PrototypeIterator::START_AT_RECEIVER | |
669 : PrototypeIterator::START_AT_PROTOTYPE); | |
670 !iter.IsAtEnd(); iter.Advance()) { | |
671 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | |
672 return JSProxy::GetElementWithHandler( | |
673 Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver, | |
674 index); | |
675 } | |
676 | |
677 // Inline the case for JSObjects. Doing so significantly improves the | |
678 // performance of fetching elements where checking the prototype chain is | |
679 // necessary. | |
680 Handle<JSObject> js_object = | |
681 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | |
682 | |
683 // Check access rights if needed. | |
684 if (js_object->IsAccessCheckNeeded()) { | |
685 if (!isolate->MayAccess(js_object)) { | |
686 return JSObject::GetElementWithFailedAccessCheck(isolate, js_object, | |
687 receiver, index); | |
688 } | |
689 } | |
690 | |
691 if (js_object->HasIndexedInterceptor()) { | |
692 return JSObject::GetElementWithInterceptor(js_object, receiver, index, | |
693 true); | |
694 } | |
695 | |
696 if (js_object->elements() != isolate->heap()->empty_fixed_array()) { | |
697 Handle<Object> result; | |
698 ASSIGN_RETURN_ON_EXCEPTION( | |
699 isolate, result, | |
700 js_object->GetElementsAccessor()->Get(receiver, js_object, index), | |
701 Object); | |
702 if (!result->IsTheHole()) return result; | |
703 } | |
704 } | |
705 | |
706 return isolate->factory()->undefined_value(); | |
707 } | |
708 | |
709 | |
710 MaybeHandle<Object> Object::SetElementWithReceiver( | 636 MaybeHandle<Object> Object::SetElementWithReceiver( |
711 Isolate* isolate, Handle<Object> object, Handle<Object> receiver, | 637 Isolate* isolate, Handle<Object> object, Handle<Object> receiver, |
712 uint32_t index, Handle<Object> value, LanguageMode language_mode) { | 638 uint32_t index, Handle<Object> value, LanguageMode language_mode) { |
713 // Iterate up the prototype chain until an element is found or the null | 639 // Iterate up the prototype chain until an element is found or the null |
714 // prototype is encountered. | 640 // prototype is encountered. |
715 bool done = false; | 641 bool done = false; |
716 for (PrototypeIterator iter(isolate, object, | 642 for (PrototypeIterator iter(isolate, object, |
717 object->IsJSProxy() || object->IsJSObject() | 643 object->IsJSProxy() || object->IsJSObject() |
718 ? PrototypeIterator::START_AT_RECEIVER | 644 ? PrototypeIterator::START_AT_RECEIVER |
719 : PrototypeIterator::START_AT_PROTOTYPE); | 645 : PrototypeIterator::START_AT_PROTOTYPE); |
(...skipping 7521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8241 GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( | 8167 GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( |
8242 this, length() - new_length); | 8168 this, length() - new_length); |
8243 } | 8169 } |
8244 } | 8170 } |
8245 | 8171 |
8246 | 8172 |
8247 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike( | 8173 MaybeHandle<FixedArray> FixedArray::AddKeysFromArrayLike( |
8248 Handle<FixedArray> content, Handle<JSObject> array, KeyFilter filter) { | 8174 Handle<FixedArray> content, Handle<JSObject> array, KeyFilter filter) { |
8249 DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements()); | 8175 DCHECK(array->IsJSArray() || array->HasSloppyArgumentsElements()); |
8250 ElementsAccessor* accessor = array->GetElementsAccessor(); | 8176 ElementsAccessor* accessor = array->GetElementsAccessor(); |
8251 Handle<FixedArray> result; | 8177 Handle<FixedArray> result = |
8252 ASSIGN_RETURN_ON_EXCEPTION( | 8178 accessor->AddElementsToFixedArray(array, content, filter); |
8253 array->GetIsolate(), result, | |
8254 accessor->AddElementsToFixedArray(array, content, filter), FixedArray); | |
8255 | 8179 |
8256 #ifdef ENABLE_SLOW_DCHECKS | 8180 #ifdef ENABLE_SLOW_DCHECKS |
8257 if (FLAG_enable_slow_asserts) { | 8181 if (FLAG_enable_slow_asserts) { |
8258 DisallowHeapAllocation no_allocation; | 8182 DisallowHeapAllocation no_allocation; |
8259 for (int i = 0; i < result->length(); i++) { | 8183 for (int i = 0; i < result->length(); i++) { |
8260 Object* current = result->get(i); | 8184 Object* current = result->get(i); |
8261 DCHECK(current->IsNumber() || current->IsName()); | 8185 DCHECK(current->IsNumber() || current->IsName()); |
8262 } | 8186 } |
8263 } | 8187 } |
8264 #endif | 8188 #endif |
(...skipping 4025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12290 DCHECK(array->AllowsSetElementsLength()); | 12214 DCHECK(array->AllowsSetElementsLength()); |
12291 if (!array->map()->is_observed()) { | 12215 if (!array->map()->is_observed()) { |
12292 return array->GetElementsAccessor()->SetLength(array, new_length_handle); | 12216 return array->GetElementsAccessor()->SetLength(array, new_length_handle); |
12293 } | 12217 } |
12294 | 12218 |
12295 Isolate* isolate = array->GetIsolate(); | 12219 Isolate* isolate = array->GetIsolate(); |
12296 List<uint32_t> indices; | 12220 List<uint32_t> indices; |
12297 List<Handle<Object> > old_values; | 12221 List<Handle<Object> > old_values; |
12298 Handle<Object> old_length_handle(array->length(), isolate); | 12222 Handle<Object> old_length_handle(array->length(), isolate); |
12299 uint32_t old_length = 0; | 12223 uint32_t old_length = 0; |
12300 CHECK(old_length_handle->ToArrayIndex(&old_length)); | 12224 CHECK(old_length_handle->ToArrayLength(&old_length)); |
12301 uint32_t new_length = 0; | 12225 uint32_t new_length = 0; |
12302 CHECK(new_length_handle->ToArrayIndex(&new_length)); | 12226 CHECK(new_length_handle->ToArrayLength(&new_length)); |
12303 | 12227 |
12304 static const PropertyAttributes kNoAttrFilter = NONE; | 12228 static const PropertyAttributes kNoAttrFilter = NONE; |
12305 int num_elements = array->NumberOfOwnElements(kNoAttrFilter); | 12229 int num_elements = array->NumberOfOwnElements(kNoAttrFilter); |
12306 if (num_elements > 0) { | 12230 if (num_elements > 0) { |
12307 if (old_length == static_cast<uint32_t>(num_elements)) { | 12231 if (old_length == static_cast<uint32_t>(num_elements)) { |
12308 // Simple case for arrays without holes. | 12232 // Simple case for arrays without holes. |
12309 for (uint32_t i = old_length - 1; i + 1 > new_length; --i) { | 12233 for (uint32_t i = old_length - 1; i + 1 > new_length; --i) { |
12310 if (!GetOldValue(isolate, array, i, &old_values, &indices)) break; | 12234 if (!GetOldValue(isolate, array, i, &old_values, &indices)) break; |
12311 } | 12235 } |
12312 } else { | 12236 } else { |
12313 // For sparse arrays, only iterate over existing elements. | 12237 // For sparse arrays, only iterate over existing elements. |
12314 // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over | 12238 // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over |
12315 // the to-be-removed indices twice. | 12239 // the to-be-removed indices twice. |
12316 Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements); | 12240 Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements); |
12317 array->GetOwnElementKeys(*keys, kNoAttrFilter); | 12241 array->GetOwnElementKeys(*keys, kNoAttrFilter); |
12318 while (num_elements-- > 0) { | 12242 while (num_elements-- > 0) { |
12319 uint32_t index = NumberToUint32(keys->get(num_elements)); | 12243 uint32_t index = NumberToUint32(keys->get(num_elements)); |
12320 if (index < new_length) break; | 12244 if (index < new_length) break; |
12321 if (!GetOldValue(isolate, array, index, &old_values, &indices)) break; | 12245 if (!GetOldValue(isolate, array, index, &old_values, &indices)) break; |
12322 } | 12246 } |
12323 } | 12247 } |
12324 } | 12248 } |
12325 | 12249 |
12326 Handle<Object> hresult; | 12250 Handle<Object> hresult; |
12327 ASSIGN_RETURN_ON_EXCEPTION( | 12251 ASSIGN_RETURN_ON_EXCEPTION( |
12328 isolate, hresult, | 12252 isolate, hresult, |
12329 array->GetElementsAccessor()->SetLength(array, new_length_handle), | 12253 array->GetElementsAccessor()->SetLength(array, new_length_handle), |
12330 Object); | 12254 Object); |
12331 | 12255 |
12332 CHECK(array->length()->ToArrayIndex(&new_length)); | 12256 CHECK(array->length()->ToArrayLength(&new_length)); |
12333 if (old_length == new_length) return hresult; | 12257 if (old_length == new_length) return hresult; |
12334 | 12258 |
12335 RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object); | 12259 RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object); |
12336 | 12260 |
12337 for (int i = 0; i < indices.length(); ++i) { | 12261 for (int i = 0; i < indices.length(); ++i) { |
12338 // For deletions where the property was an accessor, old_values[i] | 12262 // For deletions where the property was an accessor, old_values[i] |
12339 // will be the hole, which instructs EnqueueChangeRecord to elide | 12263 // will be the hole, which instructs EnqueueChangeRecord to elide |
12340 // the "oldValue" property. | 12264 // the "oldValue" property. |
12341 RETURN_ON_EXCEPTION( | 12265 RETURN_ON_EXCEPTION( |
12342 isolate, | 12266 isolate, |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12818 args.Call(setter, index, v8::Utils::ToLocal(value)); | 12742 args.Call(setter, index, v8::Utils::ToLocal(value)); |
12819 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 12743 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
12820 if (!result.IsEmpty()) return value; | 12744 if (!result.IsEmpty()) return value; |
12821 } | 12745 } |
12822 | 12746 |
12823 return SetElementWithoutInterceptor(object, index, value, attributes, | 12747 return SetElementWithoutInterceptor(object, index, value, attributes, |
12824 language_mode, check_prototype, set_mode); | 12748 language_mode, check_prototype, set_mode); |
12825 } | 12749 } |
12826 | 12750 |
12827 | 12751 |
12828 MaybeHandle<Object> JSObject::GetElementWithCallback( | |
12829 Handle<JSObject> object, | |
12830 Handle<Object> receiver, | |
12831 Handle<Object> structure, | |
12832 uint32_t index, | |
12833 Handle<Object> holder) { | |
12834 Isolate* isolate = object->GetIsolate(); | |
12835 DCHECK(!structure->IsForeign()); | |
12836 // api style callbacks. | |
12837 if (structure->IsExecutableAccessorInfo()) { | |
12838 Handle<ExecutableAccessorInfo> data = | |
12839 Handle<ExecutableAccessorInfo>::cast(structure); | |
12840 Object* fun_obj = data->getter(); | |
12841 v8::AccessorNameGetterCallback call_fun = | |
12842 v8::ToCData<v8::AccessorNameGetterCallback>(fun_obj); | |
12843 if (call_fun == NULL) return isolate->factory()->undefined_value(); | |
12844 Handle<JSObject> holder_handle = Handle<JSObject>::cast(holder); | |
12845 Handle<String> key = isolate->factory()->Uint32ToString(index); | |
12846 LOG(isolate, ApiNamedPropertyAccess("load", *holder_handle, *key)); | |
12847 PropertyCallbackArguments | |
12848 args(isolate, data->data(), *receiver, *holder_handle); | |
12849 v8::Handle<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(key)); | |
12850 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
12851 if (result.IsEmpty()) return isolate->factory()->undefined_value(); | |
12852 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | |
12853 result_internal->VerifyApiCallResultType(); | |
12854 // Rebox handle before return. | |
12855 return handle(*result_internal, isolate); | |
12856 } | |
12857 | |
12858 // __defineGetter__ callback | |
12859 if (structure->IsAccessorPair()) { | |
12860 Handle<Object> getter(Handle<AccessorPair>::cast(structure)->getter(), | |
12861 isolate); | |
12862 if (getter->IsSpecFunction()) { | |
12863 // TODO(rossberg): nicer would be to cast to some JSCallable here... | |
12864 return GetPropertyWithDefinedGetter( | |
12865 receiver, Handle<JSReceiver>::cast(getter)); | |
12866 } | |
12867 // Getter is not a function. | |
12868 return isolate->factory()->undefined_value(); | |
12869 } | |
12870 | |
12871 UNREACHABLE(); | |
12872 return MaybeHandle<Object>(); | |
12873 } | |
12874 | |
12875 | |
12876 MaybeHandle<Object> JSObject::SetElementWithCallback( | 12752 MaybeHandle<Object> JSObject::SetElementWithCallback( |
12877 Handle<Object> object, Handle<Object> structure, uint32_t index, | 12753 Handle<Object> object, Handle<Object> structure, uint32_t index, |
12878 Handle<Object> value, Handle<JSObject> holder, LanguageMode language_mode) { | 12754 Handle<Object> value, Handle<JSObject> holder, LanguageMode language_mode) { |
12879 Isolate* isolate = holder->GetIsolate(); | 12755 Isolate* isolate = holder->GetIsolate(); |
12880 | 12756 |
12881 // We should never get here to initialize a const with the hole | 12757 // We should never get here to initialize a const with the hole |
12882 // value since a const declaration would conflict with the setter. | 12758 // value since a const declaration would conflict with the setter. |
12883 DCHECK(!value->IsTheHole()); | 12759 DCHECK(!value->IsTheHole()); |
12884 DCHECK(!structure->IsForeign()); | 12760 DCHECK(!structure->IsForeign()); |
12885 if (structure->IsExecutableAccessorInfo()) { | 12761 if (structure->IsExecutableAccessorInfo()) { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12980 object, index, value, &found, language_mode); | 12856 object, index, value, &found, language_mode); |
12981 if (found) return result; | 12857 if (found) return result; |
12982 } | 12858 } |
12983 | 12859 |
12984 uint32_t new_capacity = capacity; | 12860 uint32_t new_capacity = capacity; |
12985 // Check if the length property of this object needs to be updated. | 12861 // Check if the length property of this object needs to be updated. |
12986 uint32_t array_length = 0; | 12862 uint32_t array_length = 0; |
12987 bool must_update_array_length = false; | 12863 bool must_update_array_length = false; |
12988 bool introduces_holes = true; | 12864 bool introduces_holes = true; |
12989 if (object->IsJSArray()) { | 12865 if (object->IsJSArray()) { |
12990 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length)); | 12866 CHECK( |
| 12867 Handle<JSArray>::cast(object)->length()->ToArrayLength(&array_length)); |
12991 introduces_holes = index > array_length; | 12868 introduces_holes = index > array_length; |
12992 if (index >= array_length) { | 12869 if (index >= array_length) { |
12993 must_update_array_length = true; | 12870 must_update_array_length = true; |
12994 array_length = index + 1; | 12871 array_length = index + 1; |
12995 } | 12872 } |
12996 } else { | 12873 } else { |
12997 introduces_holes = index >= capacity; | 12874 introduces_holes = index >= capacity; |
12998 } | 12875 } |
12999 | 12876 |
13000 // If the array is growing, and it's not growth by a single element at the | 12877 // 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... |
13175 // Update the array length if this JSObject is an array. | 13052 // Update the array length if this JSObject is an array. |
13176 if (object->IsJSArray()) { | 13053 if (object->IsJSArray()) { |
13177 JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index, | 13054 JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index, |
13178 value); | 13055 value); |
13179 } | 13056 } |
13180 | 13057 |
13181 // Attempt to put this object back in fast case. | 13058 // Attempt to put this object back in fast case. |
13182 if (object->ShouldConvertToFastElements()) { | 13059 if (object->ShouldConvertToFastElements()) { |
13183 uint32_t new_length = 0; | 13060 uint32_t new_length = 0; |
13184 if (object->IsJSArray()) { | 13061 if (object->IsJSArray()) { |
13185 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&new_length)); | 13062 CHECK( |
| 13063 Handle<JSArray>::cast(object)->length()->ToArrayLength(&new_length)); |
13186 } else { | 13064 } else { |
13187 new_length = dictionary->max_number_key() + 1; | 13065 new_length = dictionary->max_number_key() + 1; |
13188 } | 13066 } |
13189 bool has_smi_only_elements = false; | 13067 bool has_smi_only_elements = false; |
13190 bool should_convert_to_fast_double_elements = | 13068 bool should_convert_to_fast_double_elements = |
13191 object->ShouldConvertToFastDoubleElements(&has_smi_only_elements); | 13069 object->ShouldConvertToFastDoubleElements(&has_smi_only_elements); |
13192 SetFastElementsCapacitySmiMode smi_mode = | 13070 SetFastElementsCapacitySmiMode smi_mode = |
13193 has_smi_only_elements ? kForceSmiElements : kAllowSmiElements; | 13071 has_smi_only_elements ? kForceSmiElements : kAllowSmiElements; |
13194 | 13072 |
13195 if (should_convert_to_fast_double_elements) { | 13073 if (should_convert_to_fast_double_elements) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13230 object, index, value, &found, language_mode); | 13108 object, index, value, &found, language_mode); |
13231 if (found) return result; | 13109 if (found) return result; |
13232 } | 13110 } |
13233 | 13111 |
13234 // If the value object is not a heap number, switch to fast elements and try | 13112 // If the value object is not a heap number, switch to fast elements and try |
13235 // again. | 13113 // again. |
13236 bool value_is_smi = value->IsSmi(); | 13114 bool value_is_smi = value->IsSmi(); |
13237 bool introduces_holes = true; | 13115 bool introduces_holes = true; |
13238 uint32_t length = elms_length; | 13116 uint32_t length = elms_length; |
13239 if (object->IsJSArray()) { | 13117 if (object->IsJSArray()) { |
13240 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&length)); | 13118 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(&length)); |
13241 introduces_holes = index > length; | 13119 introduces_holes = index > length; |
13242 } else { | 13120 } else { |
13243 introduces_holes = index >= elms_length; | 13121 introduces_holes = index >= elms_length; |
13244 } | 13122 } |
13245 | 13123 |
13246 if (!value->IsNumber()) { | 13124 if (!value->IsNumber()) { |
13247 SetFastElementsCapacityAndLength(object, elms_length, length, | 13125 SetFastElementsCapacityAndLength(object, elms_length, length, |
13248 kDontAllowSmiElements); | 13126 kDontAllowSmiElements); |
13249 Handle<Object> result; | 13127 Handle<Object> result; |
13250 ASSIGN_RETURN_ON_EXCEPTION( | 13128 ASSIGN_RETURN_ON_EXCEPTION( |
(...skipping 16 matching lines...) Expand all Loading... |
13267 TransitionElementsKind(object, transitioned_kind); | 13145 TransitionElementsKind(object, transitioned_kind); |
13268 } | 13146 } |
13269 | 13147 |
13270 // Check whether there is extra space in the fixed array. | 13148 // Check whether there is extra space in the fixed array. |
13271 if (index < elms_length) { | 13149 if (index < elms_length) { |
13272 Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements())); | 13150 Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements())); |
13273 elms->set(index, double_value); | 13151 elms->set(index, double_value); |
13274 if (object->IsJSArray()) { | 13152 if (object->IsJSArray()) { |
13275 // Update the length of the array if needed. | 13153 // Update the length of the array if needed. |
13276 uint32_t array_length = 0; | 13154 uint32_t array_length = 0; |
13277 CHECK( | 13155 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength( |
13278 Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length)); | 13156 &array_length)); |
13279 if (index >= array_length) { | 13157 if (index >= array_length) { |
13280 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1)); | 13158 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1)); |
13281 } | 13159 } |
13282 } | 13160 } |
13283 return value; | 13161 return value; |
13284 } | 13162 } |
13285 | 13163 |
13286 // Allow gap in fast case. | 13164 // Allow gap in fast case. |
13287 if ((index - elms_length) < kMaxGap) { | 13165 if ((index - elms_length) < kMaxGap) { |
13288 // Try allocating extra space. | 13166 // Try allocating extra space. |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13429 PropertyAttributes new_attributes = maybe.FromJust(); | 13307 PropertyAttributes new_attributes = maybe.FromJust(); |
13430 | 13308 |
13431 if (old_attributes == ABSENT) { | 13309 if (old_attributes == ABSENT) { |
13432 if (object->IsJSArray() && | 13310 if (object->IsJSArray() && |
13433 !old_length_handle->SameValue( | 13311 !old_length_handle->SameValue( |
13434 Handle<JSArray>::cast(object)->length())) { | 13312 Handle<JSArray>::cast(object)->length())) { |
13435 new_length_handle = handle(Handle<JSArray>::cast(object)->length(), | 13313 new_length_handle = handle(Handle<JSArray>::cast(object)->length(), |
13436 isolate); | 13314 isolate); |
13437 uint32_t old_length = 0; | 13315 uint32_t old_length = 0; |
13438 uint32_t new_length = 0; | 13316 uint32_t new_length = 0; |
13439 CHECK(old_length_handle->ToArrayIndex(&old_length)); | 13317 CHECK(old_length_handle->ToArrayLength(&old_length)); |
13440 CHECK(new_length_handle->ToArrayIndex(&new_length)); | 13318 CHECK(new_length_handle->ToArrayLength(&new_length)); |
13441 | 13319 |
13442 RETURN_ON_EXCEPTION( | 13320 RETURN_ON_EXCEPTION( |
13443 isolate, BeginPerformSplice(Handle<JSArray>::cast(object)), Object); | 13321 isolate, BeginPerformSplice(Handle<JSArray>::cast(object)), Object); |
13444 RETURN_ON_EXCEPTION( | 13322 RETURN_ON_EXCEPTION( |
13445 isolate, EnqueueChangeRecord(object, "add", name, old_value), Object); | 13323 isolate, EnqueueChangeRecord(object, "add", name, old_value), Object); |
13446 RETURN_ON_EXCEPTION( | 13324 RETURN_ON_EXCEPTION( |
13447 isolate, EnqueueChangeRecord(object, "update", | 13325 isolate, EnqueueChangeRecord(object, "update", |
13448 isolate->factory()->length_string(), | 13326 isolate->factory()->length_string(), |
13449 old_length_handle), | 13327 old_length_handle), |
13450 Object); | 13328 Object); |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13618 handle(JSArray::cast(site->transition_info())); | 13496 handle(JSArray::cast(site->transition_info())); |
13619 ElementsKind kind = transition_info->GetElementsKind(); | 13497 ElementsKind kind = transition_info->GetElementsKind(); |
13620 // if kind is holey ensure that to_kind is as well. | 13498 // if kind is holey ensure that to_kind is as well. |
13621 if (IsHoleyElementsKind(kind)) { | 13499 if (IsHoleyElementsKind(kind)) { |
13622 to_kind = GetHoleyElementsKind(to_kind); | 13500 to_kind = GetHoleyElementsKind(to_kind); |
13623 } | 13501 } |
13624 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { | 13502 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { |
13625 // If the array is huge, it's not likely to be defined in a local | 13503 // If the array is huge, it's not likely to be defined in a local |
13626 // function, so we shouldn't make new instances of it very often. | 13504 // function, so we shouldn't make new instances of it very often. |
13627 uint32_t length = 0; | 13505 uint32_t length = 0; |
13628 CHECK(transition_info->length()->ToArrayIndex(&length)); | 13506 CHECK(transition_info->length()->ToArrayLength(&length)); |
13629 if (length <= kMaximumArrayBytesToPretransition) { | 13507 if (length <= kMaximumArrayBytesToPretransition) { |
13630 if (FLAG_trace_track_allocation_sites) { | 13508 if (FLAG_trace_track_allocation_sites) { |
13631 bool is_nested = site->IsNestedSite(); | 13509 bool is_nested = site->IsNestedSite(); |
13632 PrintF( | 13510 PrintF( |
13633 "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n", | 13511 "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n", |
13634 reinterpret_cast<void*>(*site), | 13512 reinterpret_cast<void*>(*site), |
13635 is_nested ? "(nested)" : "", | 13513 is_nested ? "(nested)" : "", |
13636 ElementsKindToString(kind), | 13514 ElementsKindToString(kind), |
13637 ElementsKindToString(to_kind)); | 13515 ElementsKindToString(to_kind)); |
13638 } | 13516 } |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13732 uint32_t capacity = static_cast<uint32_t>(elms->length()); | 13610 uint32_t capacity = static_cast<uint32_t>(elms->length()); |
13733 uint32_t length = capacity; | 13611 uint32_t length = capacity; |
13734 | 13612 |
13735 if (object->IsJSArray()) { | 13613 if (object->IsJSArray()) { |
13736 Object* raw_length = Handle<JSArray>::cast(object)->length(); | 13614 Object* raw_length = Handle<JSArray>::cast(object)->length(); |
13737 if (raw_length->IsUndefined()) { | 13615 if (raw_length->IsUndefined()) { |
13738 // If length is undefined, then JSArray is being initialized and has no | 13616 // If length is undefined, then JSArray is being initialized and has no |
13739 // elements, assume a length of zero. | 13617 // elements, assume a length of zero. |
13740 length = 0; | 13618 length = 0; |
13741 } else { | 13619 } else { |
13742 CHECK(raw_length->ToArrayIndex(&length)); | 13620 CHECK(raw_length->ToArrayLength(&length)); |
13743 } | 13621 } |
13744 } | 13622 } |
13745 | 13623 |
13746 if (IsFastSmiElementsKind(from_kind) && | 13624 if (IsFastSmiElementsKind(from_kind) && |
13747 IsFastDoubleElementsKind(to_kind)) { | 13625 IsFastDoubleElementsKind(to_kind)) { |
13748 SetFastDoubleElementsCapacityAndLength(object, capacity, length); | 13626 SetFastDoubleElementsCapacityAndLength(object, capacity, length); |
13749 JSObject::ValidateElements(object); | 13627 JSObject::ValidateElements(object); |
13750 return; | 13628 return; |
13751 } | 13629 } |
13752 | 13630 |
(...skipping 22 matching lines...) Expand all Loading... |
13775 // Transitions from HOLEY -> PACKED are not allowed. | 13653 // Transitions from HOLEY -> PACKED are not allowed. |
13776 return !IsFastHoleyElementsKind(from_kind) || | 13654 return !IsFastHoleyElementsKind(from_kind) || |
13777 IsFastHoleyElementsKind(to_kind); | 13655 IsFastHoleyElementsKind(to_kind); |
13778 } | 13656 } |
13779 | 13657 |
13780 | 13658 |
13781 void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array, | 13659 void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array, |
13782 uint32_t index, | 13660 uint32_t index, |
13783 Handle<Object> value) { | 13661 Handle<Object> value) { |
13784 uint32_t old_len = 0; | 13662 uint32_t old_len = 0; |
13785 CHECK(array->length()->ToArrayIndex(&old_len)); | 13663 CHECK(array->length()->ToArrayLength(&old_len)); |
13786 // Check to see if we need to update the length. For now, we make | 13664 // Check to see if we need to update the length. For now, we make |
13787 // sure that the length stays within 32-bits (unsigned). | 13665 // sure that the length stays within 32-bits (unsigned). |
13788 if (index >= old_len && index != 0xffffffff) { | 13666 if (index >= old_len && index != 0xffffffff) { |
13789 Handle<Object> len = array->GetIsolate()->factory()->NewNumber( | 13667 Handle<Object> len = array->GetIsolate()->factory()->NewNumber( |
13790 static_cast<double>(index) + 1); | 13668 static_cast<double>(index) + 1); |
13791 array->set_length(*len); | 13669 array->set_length(*len); |
13792 } | 13670 } |
13793 } | 13671 } |
13794 | 13672 |
13795 | 13673 |
13796 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) { | 13674 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) { |
13797 LookupIterator it(array, array->GetIsolate()->factory()->length_string(), | 13675 LookupIterator it(array, array->GetIsolate()->factory()->length_string(), |
13798 LookupIterator::OWN_SKIP_INTERCEPTOR); | 13676 LookupIterator::OWN_SKIP_INTERCEPTOR); |
13799 CHECK_NE(LookupIterator::ACCESS_CHECK, it.state()); | 13677 CHECK_NE(LookupIterator::ACCESS_CHECK, it.state()); |
13800 CHECK(it.IsFound()); | 13678 CHECK(it.IsFound()); |
13801 CHECK_EQ(LookupIterator::ACCESSOR, it.state()); | 13679 CHECK_EQ(LookupIterator::ACCESSOR, it.state()); |
13802 return it.IsReadOnly(); | 13680 return it.IsReadOnly(); |
13803 } | 13681 } |
13804 | 13682 |
13805 | 13683 |
13806 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array, | 13684 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array, |
13807 uint32_t index) { | 13685 uint32_t index) { |
13808 uint32_t length = 0; | 13686 uint32_t length = 0; |
13809 CHECK(array->length()->ToArrayIndex(&length)); | 13687 CHECK(array->length()->ToArrayLength(&length)); |
13810 if (length <= index) return HasReadOnlyLength(array); | 13688 if (length <= index) return HasReadOnlyLength(array); |
13811 return false; | 13689 return false; |
13812 } | 13690 } |
13813 | 13691 |
13814 | 13692 |
13815 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) { | 13693 MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) { |
13816 Isolate* isolate = array->GetIsolate(); | 13694 Isolate* isolate = array->GetIsolate(); |
13817 Handle<Name> length = isolate->factory()->length_string(); | 13695 Handle<Name> length = isolate->factory()->length_string(); |
13818 THROW_NEW_ERROR( | 13696 THROW_NEW_ERROR( |
13819 isolate, | 13697 isolate, |
13820 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, length, array), | 13698 NewTypeError(MessageTemplate::kStrictReadOnlyProperty, length, array), |
13821 Object); | 13699 Object); |
13822 } | 13700 } |
13823 | 13701 |
13824 | 13702 |
13825 MaybeHandle<Object> JSObject::GetElementWithInterceptor(Handle<JSObject> object, | |
13826 Handle<Object> receiver, | |
13827 uint32_t index, | |
13828 bool check_prototype) { | |
13829 Isolate* isolate = object->GetIsolate(); | |
13830 | |
13831 // Make sure that the top context does not change when doing | |
13832 // callbacks or interceptor calls. | |
13833 AssertNoContextChange ncc(isolate); | |
13834 | |
13835 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor(), isolate); | |
13836 if (!interceptor->getter()->IsUndefined()) { | |
13837 v8::IndexedPropertyGetterCallback getter = | |
13838 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); | |
13839 LOG(isolate, | |
13840 ApiIndexedPropertyAccess("interceptor-indexed-get", *object, index)); | |
13841 PropertyCallbackArguments | |
13842 args(isolate, interceptor->data(), *receiver, *object); | |
13843 v8::Handle<v8::Value> result = args.Call(getter, index); | |
13844 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
13845 if (!result.IsEmpty()) { | |
13846 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | |
13847 result_internal->VerifyApiCallResultType(); | |
13848 // Rebox handle before return. | |
13849 return handle(*result_internal, isolate); | |
13850 } | |
13851 } | |
13852 | |
13853 if (!check_prototype) return MaybeHandle<Object>(); | |
13854 | |
13855 ElementsAccessor* handler = object->GetElementsAccessor(); | |
13856 Handle<Object> result; | |
13857 ASSIGN_RETURN_ON_EXCEPTION( | |
13858 isolate, result, handler->Get(receiver, object, index), | |
13859 Object); | |
13860 if (!result->IsTheHole()) return result; | |
13861 | |
13862 PrototypeIterator iter(isolate, object); | |
13863 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); | |
13864 return Object::GetElementWithReceiver( | |
13865 isolate, PrototypeIterator::GetCurrent(iter), receiver, index); | |
13866 } | |
13867 | |
13868 | |
13869 bool JSObject::HasDenseElements() { | 13703 bool JSObject::HasDenseElements() { |
13870 int capacity = 0; | 13704 int capacity = 0; |
13871 int used = 0; | 13705 int used = 0; |
13872 GetElementsCapacityAndUsage(&capacity, &used); | 13706 GetElementsCapacityAndUsage(&capacity, &used); |
13873 return (capacity == 0) || (used > (capacity / 2)); | 13707 return (capacity == 0) || (used > (capacity / 2)); |
13874 } | 13708 } |
13875 | 13709 |
13876 | 13710 |
13877 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { | 13711 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { |
13878 *capacity = 0; | 13712 *capacity = 0; |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14002 dictionary = SeededNumberDictionary::cast(elements); | 13836 dictionary = SeededNumberDictionary::cast(elements); |
14003 } | 13837 } |
14004 // If an element has been added at a very high index in the elements | 13838 // If an element has been added at a very high index in the elements |
14005 // dictionary, we cannot go back to fast case. | 13839 // dictionary, we cannot go back to fast case. |
14006 if (dictionary->requires_slow_elements()) return false; | 13840 if (dictionary->requires_slow_elements()) return false; |
14007 // If the dictionary backing storage takes up roughly half as much | 13841 // If the dictionary backing storage takes up roughly half as much |
14008 // space (in machine words) as a fast-case backing storage would, | 13842 // space (in machine words) as a fast-case backing storage would, |
14009 // the object should have fast elements. | 13843 // the object should have fast elements. |
14010 uint32_t array_size = 0; | 13844 uint32_t array_size = 0; |
14011 if (IsJSArray()) { | 13845 if (IsJSArray()) { |
14012 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size)); | 13846 CHECK(JSArray::cast(this)->length()->ToArrayLength(&array_size)); |
14013 } else { | 13847 } else { |
14014 array_size = dictionary->max_number_key(); | 13848 array_size = dictionary->max_number_key(); |
14015 } | 13849 } |
14016 uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) * | 13850 uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) * |
14017 SeededNumberDictionary::kEntrySize; | 13851 SeededNumberDictionary::kEntrySize; |
14018 return 2 * dictionary_size >= array_size; | 13852 return 2 * dictionary_size >= array_size; |
14019 } | 13853 } |
14020 | 13854 |
14021 | 13855 |
14022 bool JSObject::ShouldConvertToFastDoubleElements( | 13856 bool JSObject::ShouldConvertToFastDoubleElements( |
(...skipping 3399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17422 Handle<Object> new_value) { | 17256 Handle<Object> new_value) { |
17423 if (cell->value() != *new_value) { | 17257 if (cell->value() != *new_value) { |
17424 cell->set_value(*new_value); | 17258 cell->set_value(*new_value); |
17425 Isolate* isolate = cell->GetIsolate(); | 17259 Isolate* isolate = cell->GetIsolate(); |
17426 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17260 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17427 isolate, DependentCode::kPropertyCellChangedGroup); | 17261 isolate, DependentCode::kPropertyCellChangedGroup); |
17428 } | 17262 } |
17429 } | 17263 } |
17430 } // namespace internal | 17264 } // namespace internal |
17431 } // namespace v8 | 17265 } // namespace v8 |
OLD | NEW |