Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(496)

Side by Side Diff: src/objects.cc

Issue 1159433003: Use GetProperty for getting elements. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comments Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698