From 161cc3cd2ab72f547b6136de720e35acaa3f4b1b Mon Sep 17 00:00:00 2001 From: "rafaelw@chromium.org" Date: Thu, 14 Nov 2013 17:30:48 +0000 Subject: [PATCH] Handlify JSObject::SetElement & brethren Because SetElement & co are interdependent, this patch handlfies all of JSObject:: -SetElement -SetFastElement -SetDictionaryElement -SetFastDoubleElement -SetElementWithInterceptor -SetElementWithoutInterceptor -SetElementWithCallbackSetterInPrototype R=mstarzinger@chromium.org LOG=N Review URL: https://codereview.chromium.org/66803002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17757 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/factory.cc | 9 + src/factory.h | 3 + src/objects.cc | 796 ++++++++++++++++++++++++++--------------------- src/objects.h | 115 +++++-- src/runtime.cc | 18 +- test/cctest/test-heap.cc | 12 +- 6 files changed, 546 insertions(+), 407 deletions(-) diff --git a/src/factory.cc b/src/factory.cc index a7cc080..01f5854 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -451,6 +451,15 @@ Handle Factory::NewStruct(InstanceType type) { } +Handle Factory::NewAliasedArgumentsEntry( + int aliased_context_slot) { + Handle entry = Handle::cast( + NewStruct(ALIASED_ARGUMENTS_ENTRY_TYPE)); + entry->set_aliased_context_slot(aliased_context_slot); + return entry; +} + + Handle Factory::NewDeclaredAccessorDescriptor() { return Handle::cast( NewStruct(DECLARED_ACCESSOR_DESCRIPTOR_TYPE)); diff --git a/src/factory.h b/src/factory.h index 663f56f..92086d4 100644 --- a/src/factory.h +++ b/src/factory.h @@ -224,6 +224,9 @@ class Factory { // the old generation). Handle NewStruct(InstanceType type); + Handle NewAliasedArgumentsEntry( + int aliased_context_slot); + Handle NewDeclaredAccessorDescriptor(); Handle NewDeclaredAccessorInfo(); diff --git a/src/objects.cc b/src/objects.cc index 651ad6f..f063da7 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -2972,52 +2972,44 @@ Handle JSReceiver::SetPropertyWithDefinedSetter( } -MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( +Handle JSObject::SetElementWithCallbackSetterInPrototypes( + Handle object, uint32_t index, - Object* value, + Handle value, bool* found, StrictModeFlag strict_mode) { - Heap* heap = GetHeap(); - for (Object* pt = GetPrototype(); - pt != heap->null_value(); - pt = pt->GetPrototype(GetIsolate())) { - if (pt->IsJSProxy()) { - Isolate* isolate = GetIsolate(); - HandleScope scope(isolate); - Handle proxy(JSProxy::cast(pt)); - Handle self(this, isolate); - Handle name = isolate->factory()->Uint32ToString(index); - Handle value_handle(value, isolate); - Handle result = JSProxy::SetPropertyViaPrototypesWithHandler( - proxy, self, name, value_handle, NONE, strict_mode, found); - RETURN_IF_EMPTY_HANDLE(isolate, result); - return *result; - } - if (!JSObject::cast(pt)->HasDictionaryElements()) { + Isolate *isolate = object->GetIsolate(); + for (Handle proto = handle(object->GetPrototype(), isolate); + !proto->IsNull(); + proto = handle(proto->GetPrototype(isolate), isolate)) { + if (proto->IsJSProxy()) { + return JSProxy::SetPropertyViaPrototypesWithHandler( + Handle::cast(proto), + object, + isolate->factory()->Uint32ToString(index), // name + value, + NONE, + strict_mode, + found); + } + Handle js_proto = Handle::cast(proto); + if (!js_proto->HasDictionaryElements()) { continue; } - SeededNumberDictionary* dictionary = - JSObject::cast(pt)->element_dictionary(); + Handle dictionary(js_proto->element_dictionary()); int entry = dictionary->FindEntry(index); if (entry != SeededNumberDictionary::kNotFound) { PropertyDetails details = dictionary->DetailsAt(entry); if (details.type() == CALLBACKS) { *found = true; - Isolate* isolate = GetIsolate(); - HandleScope scope(isolate); - Handle self(this, isolate); Handle structure(dictionary->ValueAt(entry), isolate); - Handle value_handle(value, isolate); - Handle holder(JSObject::cast(pt)); - Handle result = SetElementWithCallback( - self, structure, index, value_handle, holder, strict_mode); - RETURN_IF_EMPTY_HANDLE(isolate, result); - return *result; + return SetElementWithCallback(object, structure, index, value, js_proto, + strict_mode); } } } *found = false; - return heap->the_hole_value(); + return isolate->factory()->the_hole_value(); } @@ -6262,7 +6254,6 @@ void JSObject::SetElementCallback(Handle object, Handle dictionary = NormalizeElements(object); ASSERT(object->HasDictionaryElements() || object->HasDictionaryArgumentsElements()); - // Update the dictionary with the new CALLBACKS property. dictionary = SeededNumberDictionary::Set(dictionary, index, structure, details); @@ -11216,6 +11207,18 @@ void Code::Disassemble(const char* name, FILE* out) { #endif // ENABLE_DISASSEMBLER +Handle JSObject::SetFastElementsCapacityAndLength( + Handle object, + int capacity, + int length, + SetFastElementsCapacitySmiMode smi_mode) { + CALL_HEAP_FUNCTION( + object->GetIsolate(), + object->SetFastElementsCapacityAndLength(capacity, length, smi_mode), + FixedArray); +} + + MaybeObject* JSObject::SetFastElementsCapacityAndLength( int capacity, int length, @@ -11302,6 +11305,16 @@ bool Code::IsWeakEmbeddedObject(Kind kind, Object* object) { return false; } + +void JSObject::SetFastDoubleElementsCapacityAndLength(Handle object, + int capacity, + int length) { + CALL_HEAP_FUNCTION_VOID( + object->GetIsolate(), + object->SetFastDoubleElementsCapacityAndLength(capacity, length)); +} + + MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( int capacity, int length) { @@ -11939,42 +11952,38 @@ AccessorPair* JSObject::GetLocalElementAccessorPair(uint32_t index) { } -MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index, - Object* value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - bool check_prototype, - SetPropertyMode set_mode) { - Isolate* isolate = GetIsolate(); - HandleScope scope(isolate); +Handle JSObject::SetElementWithInterceptor( + Handle object, + uint32_t index, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode, + bool check_prototype, + SetPropertyMode set_mode) { + Isolate* isolate = object->GetIsolate(); // Make sure that the top context does not change when doing // callbacks or interceptor calls. AssertNoContextChange ncc(isolate); - Handle interceptor(GetIndexedInterceptor()); - Handle this_handle(this); - Handle value_handle(value, isolate); + Handle interceptor(object->GetIndexedInterceptor()); if (!interceptor->setter()->IsUndefined()) { v8::IndexedPropertySetterCallback setter = v8::ToCData(interceptor->setter()); LOG(isolate, - ApiIndexedPropertyAccess("interceptor-indexed-set", this, index)); - PropertyCallbackArguments args(isolate, interceptor->data(), this, this); + ApiIndexedPropertyAccess("interceptor-indexed-set", *object, index)); + PropertyCallbackArguments args(isolate, interceptor->data(), *object, + *object); v8::Handle result = - args.Call(setter, index, v8::Utils::ToLocal(value_handle)); - RETURN_IF_SCHEDULED_EXCEPTION(isolate); - if (!result.IsEmpty()) return *value_handle; - } - MaybeObject* raw_result = - this_handle->SetElementWithoutInterceptor(index, - *value_handle, - attributes, - strict_mode, - check_prototype, - set_mode); - RETURN_IF_SCHEDULED_EXCEPTION(isolate); - return raw_result; + args.Call(setter, index, v8::Utils::ToLocal(value)); + RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); + if (!result.IsEmpty()) return value; + } + + return SetElementWithoutInterceptor(object, index, value, attributes, + strict_mode, + check_prototype, + set_mode); } @@ -12122,41 +12131,39 @@ bool JSObject::HasDictionaryArgumentsElements() { // Adding n elements in fast case is O(n*n). // Note: revisit design to have dual undefined values to capture absent // elements. -MaybeObject* JSObject::SetFastElement(uint32_t index, - Object* value, - StrictModeFlag strict_mode, - bool check_prototype) { - ASSERT(HasFastSmiOrObjectElements() || - HasFastArgumentsElements()); +Handle JSObject::SetFastElement(Handle object, + uint32_t index, + Handle value, + StrictModeFlag strict_mode, + bool check_prototype) { + ASSERT(object->HasFastSmiOrObjectElements() || + object->HasFastArgumentsElements()); + + Isolate* isolate = object->GetIsolate(); // Array optimizations rely on the prototype lookups of Array objects always // returning undefined. If there is a store to the initial prototype object, // make sure all of these optimizations are invalidated. - Isolate* isolate(GetIsolate()); - if (isolate->is_initial_object_prototype(this) || - isolate->is_initial_array_prototype(this)) { - HandleScope scope(GetIsolate()); - map()->dependent_code()->DeoptimizeDependentCodeGroup( - GetIsolate(), + if (isolate->is_initial_object_prototype(*object) || + isolate->is_initial_array_prototype(*object)) { + object->map()->dependent_code()->DeoptimizeDependentCodeGroup(isolate, DependentCode::kElementsCantBeAddedGroup); } - FixedArray* backing_store = FixedArray::cast(elements()); - if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { - backing_store = FixedArray::cast(backing_store->get(1)); + Handle backing_store(FixedArray::cast(object->elements())); + if (backing_store->map() == + isolate->heap()->non_strict_arguments_elements_map()) { + backing_store = handle(FixedArray::cast(backing_store->get(1))); } else { - MaybeObject* maybe = EnsureWritableFastElements(); - if (!maybe->To(&backing_store)) return maybe; + backing_store = EnsureWritableFastElements(object); } uint32_t capacity = static_cast(backing_store->length()); if (check_prototype && (index >= capacity || backing_store->get(index)->IsTheHole())) { bool found; - MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, - value, - &found, - strict_mode); + Handle result = SetElementWithCallbackSetterInPrototypes( + object, index, value, &found, strict_mode); if (found) return result; } @@ -12165,8 +12172,8 @@ MaybeObject* JSObject::SetFastElement(uint32_t index, uint32_t array_length = 0; bool must_update_array_length = false; bool introduces_holes = true; - if (IsJSArray()) { - CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); + if (object->IsJSArray()) { + CHECK(Handle::cast(object)->length()->ToArrayIndex(&array_length)); introduces_holes = index > array_length; if (index >= array_length) { must_update_array_length = true; @@ -12178,13 +12185,12 @@ MaybeObject* JSObject::SetFastElement(uint32_t index, // If the array is growing, and it's not growth by a single element at the // end, make sure that the ElementsKind is HOLEY. - ElementsKind elements_kind = GetElementsKind(); + ElementsKind elements_kind = object->GetElementsKind(); if (introduces_holes && IsFastElementsKind(elements_kind) && !IsFastHoleyElementsKind(elements_kind)) { ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); - MaybeObject* maybe = TransitionElementsKind(transitioned_kind); - if (maybe->IsFailure()) return maybe; + TransitionElementsKind(object, transitioned_kind); } // Check if the capacity of the backing store needs to be increased, or if @@ -12194,94 +12200,79 @@ MaybeObject* JSObject::SetFastElement(uint32_t index, if ((index - capacity) < kMaxGap) { new_capacity = NewElementsCapacity(index + 1); ASSERT(new_capacity > index); - if (!ShouldConvertToSlowElements(new_capacity)) { + if (!object->ShouldConvertToSlowElements(new_capacity)) { convert_to_slow = false; } } if (convert_to_slow) { - MaybeObject* result = NormalizeElements(); - if (result->IsFailure()) return result; - return SetDictionaryElement(index, value, NONE, strict_mode, + NormalizeElements(object); + return SetDictionaryElement(object, index, value, NONE, strict_mode, check_prototype); } } // Convert to fast double elements if appropriate. - if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { + if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { // Consider fixing the boilerplate as well if we have one. ElementsKind to_kind = IsHoleyElementsKind(elements_kind) ? FAST_HOLEY_DOUBLE_ELEMENTS : FAST_DOUBLE_ELEMENTS; - MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); - if (maybe_failure->IsFailure()) return maybe_failure; + UpdateAllocationSite(object, to_kind); - MaybeObject* maybe = - SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); - if (maybe->IsFailure()) return maybe; - FixedDoubleArray::cast(elements())->set(index, value->Number()); - ValidateElements(); + SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length); + FixedDoubleArray::cast(object->elements())->set(index, value->Number()); + object->ValidateElements(); return value; } // Change elements kind from Smi-only to generic FAST if necessary. - if (HasFastSmiElements() && !value->IsSmi()) { - Map* new_map; - ElementsKind kind = HasFastHoleyElements() + if (object->HasFastSmiElements() && !value->IsSmi()) { + ElementsKind kind = object->HasFastHoleyElements() ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; - MaybeObject* maybe_failure = UpdateAllocationSite(kind); - if (maybe_failure->IsFailure()) return maybe_failure; - - MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), - kind); - if (!maybe_new_map->To(&new_map)) return maybe_new_map; - - set_map(new_map); + UpdateAllocationSite(object, kind); + object->set_map(*GetElementsTransitionMap(object, kind)); + ASSERT(IsFastObjectElementsKind(object->GetElementsKind())); } // Increase backing store capacity if that's been decided previously. if (new_capacity != capacity) { - FixedArray* new_elements; SetFastElementsCapacitySmiMode smi_mode = - value->IsSmi() && HasFastSmiElements() + value->IsSmi() && object->HasFastSmiElements() ? kAllowSmiElements : kDontAllowSmiElements; - { MaybeObject* maybe = - SetFastElementsCapacityAndLength(new_capacity, - array_length, - smi_mode); - if (!maybe->To(&new_elements)) return maybe; - } - new_elements->set(index, value); - ValidateElements(); + Handle new_elements = + SetFastElementsCapacityAndLength(object, new_capacity, array_length, + smi_mode); + new_elements->set(index, *value); + object->ValidateElements(); return value; } // Finally, set the new element and length. - ASSERT(elements()->IsFixedArray()); - backing_store->set(index, value); + ASSERT(object->elements()->IsFixedArray()); + backing_store->set(index, *value); if (must_update_array_length) { - JSArray::cast(this)->set_length(Smi::FromInt(array_length)); + Handle::cast(object)->set_length(Smi::FromInt(array_length)); } return value; } -MaybeObject* JSObject::SetDictionaryElement(uint32_t index, - Object* value_raw, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - bool check_prototype, - SetPropertyMode set_mode) { - ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); - Isolate* isolate = GetIsolate(); - Heap* heap = isolate->heap(); - Handle self(this); - Handle value(value_raw, isolate); +Handle JSObject::SetDictionaryElement(Handle object, + uint32_t index, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode, + bool check_prototype, + SetPropertyMode set_mode) { + ASSERT(object->HasDictionaryElements() || + object->HasDictionaryArgumentsElements()); + Isolate* isolate = object->GetIsolate(); // Insert element in the dictionary. - Handle elements(FixedArray::cast(this->elements())); + Handle elements(FixedArray::cast(object->elements())); bool is_arguments = - (elements->map() == heap->non_strict_arguments_elements_map()); + (elements->map() == isolate->heap()->non_strict_arguments_elements_map()); Handle dictionary(is_arguments ? SeededNumberDictionary::cast(elements->get(1)) : SeededNumberDictionary::cast(*elements)); @@ -12291,10 +12282,8 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index, Handle element(dictionary->ValueAt(entry), isolate); PropertyDetails details = dictionary->DetailsAt(entry); if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) { - Handle result = SetElementWithCallback(self, element, index, - value, self, strict_mode); - RETURN_IF_EMPTY_HANDLE(isolate, result); - return *result; + return SetElementWithCallback(object, element, index, value, object, + strict_mode); } else { dictionary->UpdateMaxNumberKey(index); // If a value has not been initialized we allow writing to it even if it @@ -12306,21 +12295,22 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index, dictionary->DetailsAtPut(entry, details); } else if (details.IsReadOnly() && !element->IsTheHole()) { if (strict_mode == kNonStrictMode) { - return isolate->heap()->undefined_value(); + return isolate->factory()->undefined_value(); } else { - Handle holder(this, isolate); Handle number = isolate->factory()->NewNumberFromUint(index); - Handle args[2] = { number, holder }; + Handle args[2] = { number, object }; Handle error = isolate->factory()->NewTypeError("strict_read_only_property", HandleVector(args, 2)); - return isolate->Throw(*error); + isolate->Throw(*error); + return Handle(); } } // Elements of the arguments object in slow mode might be slow aliases. if (is_arguments && element->IsAliasedArgumentsEntry()) { - AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*element); - Context* context = Context::cast(elements->get(0)); + Handle entry = + Handle::cast(element); + Handle context(Context::cast(elements->get(0))); int context_index = entry->aliased_context_slot(); ASSERT(!context->get(context_index)->IsTheHole()); context->set(context_index, *value); @@ -12334,15 +12324,16 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index, // Can cause GC! if (check_prototype) { bool found; - MaybeObject* result = SetElementWithCallbackSetterInPrototypes( - index, *value, &found, strict_mode); + Handle result = SetElementWithCallbackSetterInPrototypes(object, + index, value, &found, strict_mode); if (found) return result; } + // When we set the is_extensible flag to false we always force the // element into dictionary mode (and force them to stay there). - if (!self->map()->is_extensible()) { + if (!object->map()->is_extensible()) { if (strict_mode == kNonStrictMode) { - return isolate->heap()->undefined_value(); + return isolate->factory()->undefined_value(); } else { Handle number = isolate->factory()->NewNumberFromUint(index); Handle name = isolate->factory()->NumberToString(number); @@ -12350,36 +12341,36 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index, Handle error = isolate->factory()->NewTypeError("object_not_extensible", HandleVector(args, 1)); - return isolate->Throw(*error); + isolate->Throw(*error); + return Handle(); } } - FixedArrayBase* new_dictionary; + PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); - MaybeObject* maybe = dictionary->AddNumberEntry(index, *value, details); - if (!maybe->To(&new_dictionary)) return maybe; - if (*dictionary != SeededNumberDictionary::cast(new_dictionary)) { + Handle new_dictionary = + SeededNumberDictionary::AddNumberEntry(dictionary, index, value, + details); + if (*dictionary != *new_dictionary) { if (is_arguments) { - elements->set(1, new_dictionary); + elements->set(1, *new_dictionary); } else { - self->set_elements(new_dictionary); + object->set_elements(*new_dictionary); } - dictionary = - handle(SeededNumberDictionary::cast(new_dictionary), isolate); + dictionary = new_dictionary; } } // Update the array length if this JSObject is an array. - if (self->IsJSArray()) { - MaybeObject* result = - JSArray::cast(*self)->JSArrayUpdateLengthFromIndex(index, *value); - if (result->IsFailure()) return result; + if (object->IsJSArray()) { + JSArray::JSArrayUpdateLengthFromIndex(Handle::cast(object), index, + value); } // Attempt to put this object back in fast case. - if (self->ShouldConvertToFastElements()) { + if (object->ShouldConvertToFastElements()) { uint32_t new_length = 0; - if (self->IsJSArray()) { - CHECK(JSArray::cast(*self)->length()->ToArrayIndex(&new_length)); + if (object->IsJSArray()) { + CHECK(Handle::cast(object)->length()->ToArrayIndex(&new_length)); } else { new_length = dictionary->max_number_key() + 1; } @@ -12388,47 +12379,47 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index, : kDontAllowSmiElements; bool has_smi_only_elements = false; bool should_convert_to_fast_double_elements = - self->ShouldConvertToFastDoubleElements(&has_smi_only_elements); + object->ShouldConvertToFastDoubleElements(&has_smi_only_elements); if (has_smi_only_elements) { smi_mode = kForceSmiElements; } - MaybeObject* result = should_convert_to_fast_double_elements - ? self->SetFastDoubleElementsCapacityAndLength(new_length, new_length) - : self->SetFastElementsCapacityAndLength( - new_length, new_length, smi_mode); - self->ValidateElements(); - if (result->IsFailure()) return result; + + if (should_convert_to_fast_double_elements) { + SetFastDoubleElementsCapacityAndLength(object, new_length, new_length); + } else { + SetFastElementsCapacityAndLength(object, new_length, new_length, + smi_mode); + } + object->ValidateElements(); #ifdef DEBUG if (FLAG_trace_normalization) { PrintF("Object elements are fast case again:\n"); - Print(); + object->Print(); } #endif } - return *value; + return value; } - -MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement( +Handle JSObject::SetFastDoubleElement( + Handle object, uint32_t index, - Object* value, + Handle value, StrictModeFlag strict_mode, bool check_prototype) { - ASSERT(HasFastDoubleElements()); + ASSERT(object->HasFastDoubleElements()); - FixedArrayBase* base_elms = FixedArrayBase::cast(elements()); + Handle base_elms(FixedArrayBase::cast(object->elements())); uint32_t elms_length = static_cast(base_elms->length()); // If storing to an element that isn't in the array, pass the store request // up the prototype chain before storing in the receiver's elements. if (check_prototype && (index >= elms_length || - FixedDoubleArray::cast(base_elms)->is_the_hole(index))) { + Handle::cast(base_elms)->is_the_hole(index))) { bool found; - MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, - value, - &found, - strict_mode); + Handle result = SetElementWithCallbackSetterInPrototypes(object, + index, value, &found, strict_mode); if (found) return result; } @@ -12437,48 +12428,47 @@ MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement( bool value_is_smi = value->IsSmi(); bool introduces_holes = true; uint32_t length = elms_length; - if (IsJSArray()) { - CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); + if (object->IsJSArray()) { + CHECK(Handle::cast(object)->length()->ToArrayIndex(&length)); introduces_holes = index > length; } else { introduces_holes = index >= elms_length; } if (!value->IsNumber()) { - MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( - elms_length, - length, - kDontAllowSmiElements); - if (maybe_obj->IsFailure()) return maybe_obj; - maybe_obj = SetFastElement(index, value, strict_mode, check_prototype); - if (maybe_obj->IsFailure()) return maybe_obj; - ValidateElements(); - return maybe_obj; + SetFastElementsCapacityAndLength(object, elms_length, length, + kDontAllowSmiElements); + Handle result = SetFastElement(object, index, value, strict_mode, + check_prototype); + RETURN_IF_EMPTY_HANDLE_VALUE(object->GetIsolate(), result, + Handle()); + object->ValidateElements(); + return result; } double double_value = value_is_smi - ? static_cast(Smi::cast(value)->value()) - : HeapNumber::cast(value)->value(); + ? static_cast(Handle::cast(value)->value()) + : Handle::cast(value)->value(); // If the array is growing, and it's not growth by a single element at the // end, make sure that the ElementsKind is HOLEY. - ElementsKind elements_kind = GetElementsKind(); + ElementsKind elements_kind = object->GetElementsKind(); if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) { ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); - MaybeObject* maybe = TransitionElementsKind(transitioned_kind); - if (maybe->IsFailure()) return maybe; + TransitionElementsKind(object, transitioned_kind); } // Check whether there is extra space in the fixed array. if (index < elms_length) { - FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); + Handle elms(FixedDoubleArray::cast(object->elements())); elms->set(index, double_value); - if (IsJSArray()) { + if (object->IsJSArray()) { // Update the length of the array if needed. uint32_t array_length = 0; - CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); + CHECK( + Handle::cast(object)->length()->ToArrayIndex(&array_length)); if (index >= array_length) { - JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); + Handle::cast(object)->set_length(Smi::FromInt(index + 1)); } } return value; @@ -12488,27 +12478,23 @@ MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement( if ((index - elms_length) < kMaxGap) { // Try allocating extra space. int new_capacity = NewElementsCapacity(index+1); - if (!ShouldConvertToSlowElements(new_capacity)) { + if (!object->ShouldConvertToSlowElements(new_capacity)) { ASSERT(static_cast(new_capacity) > index); - MaybeObject* maybe_obj = - SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1); - if (maybe_obj->IsFailure()) return maybe_obj; - FixedDoubleArray::cast(elements())->set(index, double_value); - ValidateElements(); + SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1); + FixedDoubleArray::cast(object->elements())->set(index, double_value); + object->ValidateElements(); return value; } } // Otherwise default to slow case. - ASSERT(HasFastDoubleElements()); - ASSERT(map()->has_fast_double_elements()); - ASSERT(elements()->IsFixedDoubleArray()); - Object* obj; - { MaybeObject* maybe_obj = NormalizeElements(); - if (!maybe_obj->ToObject(&obj)) return maybe_obj; - } - ASSERT(HasDictionaryElements()); - return SetElement(index, value, NONE, strict_mode, check_prototype); + ASSERT(object->HasFastDoubleElements()); + ASSERT(object->map()->has_fast_double_elements()); + ASSERT(object->elements()->IsFixedDoubleArray()); + + NormalizeElements(object); + ASSERT(object->HasDictionaryElements()); + return SetElement(object, index, value, NONE, strict_mode, check_prototype); } @@ -12531,262 +12517,258 @@ Handle JSObject::SetOwnElement(Handle object, Handle value, StrictModeFlag strict_mode) { ASSERT(!object->HasExternalArrayElements()); - CALL_HEAP_FUNCTION( - object->GetIsolate(), - object->SetElement(index, *value, NONE, strict_mode, false), - Object); + return JSObject::SetElement(object, index, value, NONE, strict_mode, false); } Handle JSObject::SetElement(Handle object, uint32_t index, Handle value, - PropertyAttributes attr, + PropertyAttributes attributes, StrictModeFlag strict_mode, bool check_prototype, SetPropertyMode set_mode) { + Isolate* isolate = object->GetIsolate(); + if (object->HasExternalArrayElements()) { if (!value->IsNumber() && !value->IsUndefined()) { bool has_exception; Handle number = - Execution::ToNumber(object->GetIsolate(), value, &has_exception); + Execution::ToNumber(isolate, value, &has_exception); if (has_exception) return Handle(); value = number; } } - CALL_HEAP_FUNCTION( - object->GetIsolate(), - object->SetElement(index, *value, attr, strict_mode, check_prototype, - set_mode), - Object); -} - - -MaybeObject* JSObject::SetElement(uint32_t index, - Object* value_raw, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - bool check_prototype, - SetPropertyMode set_mode) { - Isolate* isolate = GetIsolate(); // Check access rights if needed. - if (IsAccessCheckNeeded()) { - if (!isolate->MayIndexedAccess(this, index, v8::ACCESS_SET)) { - isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); - RETURN_IF_SCHEDULED_EXCEPTION(isolate); - return value_raw; + if (object->IsAccessCheckNeeded()) { + if (!isolate->MayIndexedAccess(*object, index, v8::ACCESS_SET)) { + isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET); + RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); + return value; } } - if (IsJSGlobalProxy()) { - Object* proto = GetPrototype(); - if (proto->IsNull()) return value_raw; + if (object->IsJSGlobalProxy()) { + Handle proto(object->GetPrototype(), isolate); + if (proto->IsNull()) return value; ASSERT(proto->IsJSGlobalObject()); - return JSObject::cast(proto)->SetElement(index, - value_raw, - attributes, - strict_mode, - check_prototype, - set_mode); + return SetElement(Handle::cast(proto), index, value, attributes, + strict_mode, + check_prototype, + set_mode); } // Don't allow element properties to be redefined for external arrays. - if (HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) { + if (object->HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) { Handle number = isolate->factory()->NewNumberFromUint(index); - Handle args[] = { handle(this, isolate), number }; + Handle args[] = { object, number }; Handle error = isolate->factory()->NewTypeError( "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args))); - return isolate->Throw(*error); + isolate->Throw(*error); + return Handle(); } // Normalize the elements to enable attributes on the property. if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) { - SeededNumberDictionary* dictionary; - MaybeObject* maybe_object = NormalizeElements(); - if (!maybe_object->To(&dictionary)) return maybe_object; + Handle dictionary = NormalizeElements(object); // Make sure that we never go back to fast case. dictionary->set_requires_slow_elements(); } - if (!(FLAG_harmony_observation && map()->is_observed())) { - return HasIndexedInterceptor() - ? SetElementWithInterceptor( - index, value_raw, attributes, strict_mode, check_prototype, set_mode) - : SetElementWithoutInterceptor( - index, value_raw, attributes, strict_mode, check_prototype, set_mode); + if (!(FLAG_harmony_observation && object->map()->is_observed())) { + return object->HasIndexedInterceptor() + ? SetElementWithInterceptor(object, index, value, attributes, strict_mode, + check_prototype, + set_mode) + : SetElementWithoutInterceptor(object, index, value, attributes, + strict_mode, + check_prototype, + set_mode); } - // From here on, everything has to be handlified. - Handle self(this); - Handle value(value_raw, isolate); - PropertyAttributes old_attributes = self->GetLocalElementAttribute(index); + PropertyAttributes old_attributes = object->GetLocalElementAttribute(index); Handle old_value = isolate->factory()->the_hole_value(); Handle old_length_handle; Handle new_length_handle; if (old_attributes != ABSENT) { - if (self->GetLocalElementAccessorPair(index) == NULL) - old_value = Object::GetElement(isolate, self, index); - } else if (self->IsJSArray()) { + if (object->GetLocalElementAccessorPair(index) == NULL) + old_value = Object::GetElement(isolate, object, index); + } else if (object->IsJSArray()) { // Store old array length in case adding an element grows the array. - old_length_handle = handle(Handle::cast(self)->length(), isolate); + old_length_handle = handle(Handle::cast(object)->length(), + isolate); } // Check for lookup interceptor - MaybeObject* result = self->HasIndexedInterceptor() - ? self->SetElementWithInterceptor( - index, *value, attributes, strict_mode, check_prototype, set_mode) - : self->SetElementWithoutInterceptor( - index, *value, attributes, strict_mode, check_prototype, set_mode); - - Handle hresult; - if (!result->ToHandle(&hresult, isolate)) return result; + Handle result = object->HasIndexedInterceptor() + ? SetElementWithInterceptor(object, index, value, attributes, strict_mode, + check_prototype, + set_mode) + : SetElementWithoutInterceptor(object, index, value, attributes, + strict_mode, + check_prototype, + set_mode); + RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle()); Handle name = isolate->factory()->Uint32ToString(index); - PropertyAttributes new_attributes = self->GetLocalElementAttribute(index); + PropertyAttributes new_attributes = object->GetLocalElementAttribute(index); if (old_attributes == ABSENT) { - if (self->IsJSArray() && - !old_length_handle->SameValue(Handle::cast(self)->length())) { - new_length_handle = handle(Handle::cast(self)->length(), + if (object->IsJSArray() && + !old_length_handle->SameValue( + Handle::cast(object)->length())) { + new_length_handle = handle(Handle::cast(object)->length(), isolate); uint32_t old_length = 0; uint32_t new_length = 0; CHECK(old_length_handle->ToArrayIndex(&old_length)); CHECK(new_length_handle->ToArrayIndex(&new_length)); - BeginPerformSplice(Handle::cast(self)); - EnqueueChangeRecord(self, "add", name, old_value); - EnqueueChangeRecord(self, "update", isolate->factory()->length_string(), + BeginPerformSplice(Handle::cast(object)); + EnqueueChangeRecord(object, "add", name, old_value); + EnqueueChangeRecord(object, "update", isolate->factory()->length_string(), old_length_handle); - EndPerformSplice(Handle::cast(self)); + EndPerformSplice(Handle::cast(object)); Handle deleted = isolate->factory()->NewJSArray(0); - EnqueueSpliceRecord(Handle::cast(self), old_length, deleted, + EnqueueSpliceRecord(Handle::cast(object), old_length, deleted, new_length - old_length); } else { - EnqueueChangeRecord(self, "add", name, old_value); + EnqueueChangeRecord(object, "add", name, old_value); } } else if (old_value->IsTheHole()) { - EnqueueChangeRecord(self, "reconfigure", name, old_value); + EnqueueChangeRecord(object, "reconfigure", name, old_value); } else { - Handle new_value = Object::GetElement(isolate, self, index); + Handle new_value = Object::GetElement(isolate, object, index); bool value_changed = !old_value->SameValue(*new_value); if (old_attributes != new_attributes) { if (!value_changed) old_value = isolate->factory()->the_hole_value(); - EnqueueChangeRecord(self, "reconfigure", name, old_value); + EnqueueChangeRecord(object, "reconfigure", name, old_value); } else if (value_changed) { - EnqueueChangeRecord(self, "update", name, old_value); + EnqueueChangeRecord(object, "update", name, old_value); } } - return *hresult; + return result; } -MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, - Object* value, - PropertyAttributes attr, - StrictModeFlag strict_mode, - bool check_prototype, - SetPropertyMode set_mode) { - ASSERT(HasDictionaryElements() || - HasDictionaryArgumentsElements() || - (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); - Isolate* isolate = GetIsolate(); +Handle JSObject::SetElementWithoutInterceptor( + Handle object, + uint32_t index, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode, + bool check_prototype, + SetPropertyMode set_mode) { + ASSERT(object->HasDictionaryElements() || + object->HasDictionaryArgumentsElements() || + (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); + Isolate* isolate = object->GetIsolate(); if (FLAG_trace_external_array_abuse && - IsExternalArrayElementsKind(GetElementsKind())) { - CheckArrayAbuse(this, "external elements write", index); + IsExternalArrayElementsKind(object->GetElementsKind())) { + CheckArrayAbuse(*object, "external elements write", index); } if (FLAG_trace_js_array_abuse && - !IsExternalArrayElementsKind(GetElementsKind())) { - if (IsJSArray()) { - CheckArrayAbuse(this, "elements write", index, true); + !IsExternalArrayElementsKind(object->GetElementsKind())) { + if (object->IsJSArray()) { + CheckArrayAbuse(*object, "elements write", index, true); } } - switch (GetElementsKind()) { + switch (object->GetElementsKind()) { case FAST_SMI_ELEMENTS: case FAST_ELEMENTS: case FAST_HOLEY_SMI_ELEMENTS: case FAST_HOLEY_ELEMENTS: - return SetFastElement(index, value, strict_mode, check_prototype); + return SetFastElement(object, index, value, strict_mode, check_prototype); case FAST_DOUBLE_ELEMENTS: case FAST_HOLEY_DOUBLE_ELEMENTS: - return SetFastDoubleElement(index, value, strict_mode, check_prototype); + return SetFastDoubleElement(object, index, value, strict_mode, + check_prototype); case EXTERNAL_PIXEL_ELEMENTS: { - ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); - return pixels->SetValue(index, value); + ExternalPixelArray* pixels = ExternalPixelArray::cast(object->elements()); + return handle(pixels->SetValue(index, *value), isolate); } case EXTERNAL_BYTE_ELEMENTS: { - ExternalByteArray* array = ExternalByteArray::cast(elements()); - return array->SetValue(index, value); + Handle array( + ExternalByteArray::cast(object->elements())); + return ExternalByteArray::SetValue(array, index, value); } case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { - ExternalUnsignedByteArray* array = - ExternalUnsignedByteArray::cast(elements()); - return array->SetValue(index, value); + Handle array( + ExternalUnsignedByteArray::cast(object->elements())); + return ExternalUnsignedByteArray::SetValue(array, index, value); } case EXTERNAL_SHORT_ELEMENTS: { - ExternalShortArray* array = ExternalShortArray::cast(elements()); - return array->SetValue(index, value); + Handle array(ExternalShortArray::cast( + object->elements())); + return ExternalShortArray::SetValue(array, index, value); } case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: { - ExternalUnsignedShortArray* array = - ExternalUnsignedShortArray::cast(elements()); - return array->SetValue(index, value); + Handle array( + ExternalUnsignedShortArray::cast(object->elements())); + return ExternalUnsignedShortArray::SetValue(array, index, value); } case EXTERNAL_INT_ELEMENTS: { - ExternalIntArray* array = ExternalIntArray::cast(elements()); - return array->SetValue(index, value); + Handle array( + ExternalIntArray::cast(object->elements())); + return ExternalIntArray::SetValue(array, index, value); } case EXTERNAL_UNSIGNED_INT_ELEMENTS: { - ExternalUnsignedIntArray* array = - ExternalUnsignedIntArray::cast(elements()); - return array->SetValue(index, value); + Handle array( + ExternalUnsignedIntArray::cast(object->elements())); + return ExternalUnsignedIntArray::SetValue(array, index, value); } case EXTERNAL_FLOAT_ELEMENTS: { - ExternalFloatArray* array = ExternalFloatArray::cast(elements()); - return array->SetValue(index, value); + Handle array( + ExternalFloatArray::cast(object->elements())); + return ExternalFloatArray::SetValue(array, index, value); } case EXTERNAL_DOUBLE_ELEMENTS: { - ExternalDoubleArray* array = ExternalDoubleArray::cast(elements()); - return array->SetValue(index, value); + Handle array( + ExternalDoubleArray::cast(object->elements())); + return ExternalDoubleArray::SetValue(array, index, value); } case DICTIONARY_ELEMENTS: - return SetDictionaryElement(index, value, attr, strict_mode, - check_prototype, set_mode); + return SetDictionaryElement(object, index, value, attributes, strict_mode, + check_prototype, + set_mode); case NON_STRICT_ARGUMENTS_ELEMENTS: { - FixedArray* parameter_map = FixedArray::cast(elements()); + Handle parameter_map(FixedArray::cast(object->elements())); uint32_t length = parameter_map->length(); - Object* probe = - (index < length - 2) ? parameter_map->get(index + 2) : NULL; - if (probe != NULL && !probe->IsTheHole()) { - Context* context = Context::cast(parameter_map->get(0)); - int context_index = Smi::cast(probe)->value(); + Handle probe = index < length - 2 ? + Handle(parameter_map->get(index + 2), isolate) : + Handle(); + if (!probe.is_null() && !probe->IsTheHole()) { + Handle context(Context::cast(parameter_map->get(0))); + int context_index = Handle::cast(probe)->value(); ASSERT(!context->get(context_index)->IsTheHole()); - context->set(context_index, value); + context->set(context_index, *value); // Redefining attributes of an aliased element destroys fast aliasing. - if (set_mode == SET_PROPERTY || attr == NONE) return value; + if (set_mode == SET_PROPERTY || attributes == NONE) return value; parameter_map->set_the_hole(index + 2); // For elements that are still writable we re-establish slow aliasing. - if ((attr & READ_ONLY) == 0) { - MaybeObject* maybe_entry = - isolate->heap()->AllocateAliasedArgumentsEntry(context_index); - if (!maybe_entry->ToObject(&value)) return maybe_entry; + if ((attributes & READ_ONLY) == 0) { + value = Handle::cast( + isolate->factory()->NewAliasedArgumentsEntry(context_index)); } } - FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); + Handle arguments(FixedArray::cast(parameter_map->get(1))); if (arguments->IsDictionary()) { - return SetDictionaryElement(index, value, attr, strict_mode, - check_prototype, set_mode); + return SetDictionaryElement(object, index, value, attributes, + strict_mode, + check_prototype, + set_mode); } else { - return SetFastElement(index, value, strict_mode, check_prototype); + return SetFastElement(object, index, value, strict_mode, + check_prototype); } } } // All possible cases have been handled above. Add a return to avoid the // complaints from the compiler. UNREACHABLE(); - return isolate->heap()->null_value(); + return isolate->factory()->null_value(); } @@ -12883,6 +12865,13 @@ void AllocationSite::AddDependentCode(Reason reason, Handle code) { } +void JSObject::UpdateAllocationSite(Handle object, + ElementsKind to_kind) { + CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), + object->UpdateAllocationSite(to_kind)); +} + + MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { if (!FLAG_track_allocation_sites || !IsJSArray()) { return this; @@ -12988,6 +12977,14 @@ bool Map::IsValidElementsTransition(ElementsKind from_kind, } +void JSArray::JSArrayUpdateLengthFromIndex(Handle array, + uint32_t index, + Handle value) { + CALL_HEAP_FUNCTION_VOID(array->GetIsolate(), + array->JSArrayUpdateLengthFromIndex(index, *value)); +} + + MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, Object* value) { uint32_t old_len = 0; @@ -13093,8 +13090,7 @@ void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { } break; case DICTIONARY_ELEMENTS: { - SeededNumberDictionary* dictionary = - SeededNumberDictionary::cast(FixedArray::cast(elements())); + SeededNumberDictionary* dictionary = element_dictionary(); *capacity = dictionary->Capacity(); *used = dictionary->NumberOfElements(); break; @@ -13193,8 +13189,7 @@ bool JSObject::ShouldConvertToFastDoubleElements( *has_smi_only_elements = false; if (FLAG_unbox_double_arrays) { ASSERT(HasDictionaryElements()); - SeededNumberDictionary* dictionary = - SeededNumberDictionary::cast(elements()); + SeededNumberDictionary* dictionary = element_dictionary(); bool found_double = false; for (int i = 0; i < dictionary->Capacity(); i++) { Object* key = dictionary->KeyAt(i); @@ -14572,7 +14567,7 @@ Handle JSObject::PrepareElementsForSort(Handle object, return handle(Smi::FromInt( ExternalArray::cast(object->elements())->length()), isolate); } else if (!object->HasFastDoubleElements()) { - JSObject::EnsureWritableFastElements(object); + EnsureWritableFastElements(object); } ASSERT(object->HasFastSmiOrObjectElements() || object->HasFastDoubleElements()); @@ -14779,12 +14774,31 @@ static MaybeObject* ExternalArrayIntSetter(Heap* heap, } +Handle ExternalByteArray::SetValue(Handle array, + uint32_t index, + Handle value) { + CALL_HEAP_FUNCTION(array->GetIsolate(), + array->SetValue(index, *value), + Object); +} + + MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) { return ExternalArrayIntSetter (GetHeap(), this, index, value); } +Handle ExternalUnsignedByteArray::SetValue( + Handle array, + uint32_t index, + Handle value) { + CALL_HEAP_FUNCTION(array->GetIsolate(), + array->SetValue(index, *value), + Object); +} + + MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index, Object* value) { return ExternalArrayIntSetter @@ -14792,6 +14806,16 @@ MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index, } +Handle ExternalShortArray::SetValue( + Handle array, + uint32_t index, + Handle value) { + CALL_HEAP_FUNCTION(array->GetIsolate(), + array->SetValue(index, *value), + Object); +} + + MaybeObject* ExternalShortArray::SetValue(uint32_t index, Object* value) { return ExternalArrayIntSetter @@ -14799,6 +14823,16 @@ MaybeObject* ExternalShortArray::SetValue(uint32_t index, } +Handle ExternalUnsignedShortArray::SetValue( + Handle array, + uint32_t index, + Handle value) { + CALL_HEAP_FUNCTION(array->GetIsolate(), + array->SetValue(index, *value), + Object); +} + + MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index, Object* value) { return ExternalArrayIntSetter @@ -14806,12 +14840,31 @@ MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index, } +Handle ExternalIntArray::SetValue(Handle array, + uint32_t index, + Handle value) { + CALL_HEAP_FUNCTION(array->GetIsolate(), + array->SetValue(index, *value), + Object); +} + + MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) { return ExternalArrayIntSetter (GetHeap(), this, index, value); } +Handle ExternalUnsignedIntArray::SetValue( + Handle array, + uint32_t index, + Handle value) { + CALL_HEAP_FUNCTION(array->GetIsolate(), + array->SetValue(index, *value), + Object); +} + + MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) { uint32_t cast_value = 0; Heap* heap = GetHeap(); @@ -14833,6 +14886,15 @@ MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) { } +Handle ExternalFloatArray::SetValue(Handle array, + uint32_t index, + Handle value) { + CALL_HEAP_FUNCTION(array->GetIsolate(), + array->SetValue(index, *value), + Object); +} + + MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) { float cast_value = static_cast(OS::nan_value()); Heap* heap = GetHeap(); @@ -14854,6 +14916,15 @@ MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) { } +Handle ExternalDoubleArray::SetValue(Handle array, + uint32_t index, + Handle value) { + CALL_HEAP_FUNCTION(array->GetIsolate(), + array->SetValue(index, *value), + Object); +} + + MaybeObject* ExternalDoubleArray::SetValue(uint32_t index, Object* value) { double double_value = OS::nan_value(); Heap* heap = GetHeap(); @@ -15475,6 +15546,15 @@ void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) { } } +Handle SeededNumberDictionary::AddNumberEntry( + Handle dictionary, + uint32_t key, + Handle value, + PropertyDetails details) { + CALL_HEAP_FUNCTION(dictionary->GetIsolate(), + dictionary->AddNumberEntry(key, *value, details), + SeededNumberDictionary); +} MaybeObject* SeededNumberDictionary::AddNumberEntry(uint32_t key, Object* value, diff --git a/src/objects.h b/src/objects.h index 6fe18fa..1c415d7 100644 --- a/src/objects.h +++ b/src/objects.h @@ -2339,24 +2339,10 @@ class JSObject: public JSReceiver { AccessorPair* GetLocalPropertyAccessorPair(Name* name); AccessorPair* GetLocalElementAccessorPair(uint32_t index); - MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index, - Object* value, - StrictModeFlag strict_mode, - bool check_prototype); - - MUST_USE_RESULT MaybeObject* SetDictionaryElement( - uint32_t index, - Object* value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - bool check_prototype, - SetPropertyMode set_mode = SET_PROPERTY); - - MUST_USE_RESULT MaybeObject* SetFastDoubleElement( - uint32_t index, - Object* value, - StrictModeFlag strict_mode, - bool check_prototype = true); + static Handle SetFastElement(Handle object, uint32_t index, + Handle value, + StrictModeFlag strict_mode, + bool check_prototype); static Handle SetOwnElement(Handle object, uint32_t index, @@ -2368,15 +2354,6 @@ class JSObject: public JSReceiver { Handle object, uint32_t index, Handle value, - PropertyAttributes attr, - StrictModeFlag strict_mode, - bool check_prototype = true, - SetPropertyMode set_mode = SET_PROPERTY); - - // A Failure object is returned if GC is needed. - MUST_USE_RESULT MaybeObject* SetElement( - uint32_t index, - Object* value, PropertyAttributes attributes, StrictModeFlag strict_mode, bool check_prototype = true, @@ -2393,6 +2370,11 @@ class JSObject: public JSReceiver { kDontAllowSmiElements }; + static Handle SetFastElementsCapacityAndLength( + Handle object, + int capacity, + int length, + SetFastElementsCapacitySmiMode smi_mode); // Replace the elements' backing store with fast elements of the given // capacity. Update the length for JSArrays. Returns the new backing // store. @@ -2400,6 +2382,10 @@ class JSObject: public JSReceiver { int capacity, int length, SetFastElementsCapacitySmiMode smi_mode); + static void SetFastDoubleElementsCapacityAndLength( + Handle object, + int capacity, + int length); MUST_USE_RESULT MaybeObject* SetFastDoubleElementsCapacityAndLength( int capacity, int length); @@ -2469,7 +2455,6 @@ class JSObject: public JSReceiver { ElementsKind to_kind); MUST_USE_RESULT MaybeObject* TransitionElementsKind(ElementsKind to_kind); - MUST_USE_RESULT MaybeObject* UpdateAllocationSite(ElementsKind to_kind); // TODO(mstarzinger): Both public because of ConvertAnsSetLocalProperty(). static void MigrateToMap(Handle object, Handle new_map); @@ -2660,6 +2645,10 @@ class JSObject: public JSReceiver { friend class JSReceiver; friend class Object; + static void UpdateAllocationSite(Handle object, + ElementsKind to_kind); + MUST_USE_RESULT MaybeObject* UpdateAllocationSite(ElementsKind to_kind); + // Used from Object::GetProperty(). static Handle GetPropertyWithFailedAccessCheck( Handle object, @@ -2687,25 +2676,42 @@ class JSObject: public JSReceiver { Handle value, Handle holder, StrictModeFlag strict_mode); - MUST_USE_RESULT MaybeObject* SetElementWithInterceptor( + static Handle SetElementWithInterceptor( + Handle object, uint32_t index, - Object* value, + Handle value, PropertyAttributes attributes, StrictModeFlag strict_mode, bool check_prototype, SetPropertyMode set_mode); - MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor( + static Handle SetElementWithoutInterceptor( + Handle object, uint32_t index, - Object* value, + Handle value, PropertyAttributes attributes, StrictModeFlag strict_mode, bool check_prototype, SetPropertyMode set_mode); - MUST_USE_RESULT MaybeObject* SetElementWithCallbackSetterInPrototypes( + static Handle SetElementWithCallbackSetterInPrototypes( + Handle object, uint32_t index, - Object* value, + Handle value, bool* found, StrictModeFlag strict_mode); + static Handle SetDictionaryElement( + Handle object, + uint32_t index, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode, + bool check_prototype, + SetPropertyMode set_mode = SET_PROPERTY); + static Handle SetFastDoubleElement( + Handle object, + uint32_t index, + Handle value, + StrictModeFlag strict_mode, + bool check_prototype = true); // Searches the prototype chain for property 'name'. If it is found and // has a setter, invoke it and set '*done' to true. If it is found and is @@ -3967,6 +3973,11 @@ class SeededNumberDictionary // Type specific at put (default NONE attributes is used when adding). MUST_USE_RESULT MaybeObject* AtNumberPut(uint32_t key, Object* value); + MUST_USE_RESULT static Handle AddNumberEntry( + Handle dictionary, + uint32_t key, + Handle value, + PropertyDetails details); MUST_USE_RESULT MaybeObject* AddNumberEntry(uint32_t key, Object* value, PropertyDetails details); @@ -4591,6 +4602,10 @@ class ExternalByteArray: public ExternalArray { MUST_USE_RESULT inline MaybeObject* get(int index); inline void set(int index, int8_t value); + static Handle SetValue(Handle array, + uint32_t index, + Handle value); + // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value); @@ -4614,6 +4629,10 @@ class ExternalUnsignedByteArray: public ExternalArray { MUST_USE_RESULT inline MaybeObject* get(int index); inline void set(int index, uint8_t value); + static Handle SetValue(Handle array, + uint32_t index, + Handle value); + // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value); @@ -4637,6 +4656,10 @@ class ExternalShortArray: public ExternalArray { MUST_USE_RESULT inline MaybeObject* get(int index); inline void set(int index, int16_t value); + static Handle SetValue(Handle array, + uint32_t index, + Handle value); + // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value); @@ -4660,6 +4683,10 @@ class ExternalUnsignedShortArray: public ExternalArray { MUST_USE_RESULT inline MaybeObject* get(int index); inline void set(int index, uint16_t value); + static Handle SetValue(Handle array, + uint32_t index, + Handle value); + // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value); @@ -4683,6 +4710,10 @@ class ExternalIntArray: public ExternalArray { MUST_USE_RESULT inline MaybeObject* get(int index); inline void set(int index, int32_t value); + static Handle SetValue(Handle array, + uint32_t index, + Handle value); + // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value); @@ -4706,6 +4737,10 @@ class ExternalUnsignedIntArray: public ExternalArray { MUST_USE_RESULT inline MaybeObject* get(int index); inline void set(int index, uint32_t value); + static Handle SetValue(Handle array, + uint32_t index, + Handle value); + // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value); @@ -4729,6 +4764,10 @@ class ExternalFloatArray: public ExternalArray { MUST_USE_RESULT inline MaybeObject* get(int index); inline void set(int index, float value); + static Handle SetValue(Handle array, + uint32_t index, + Handle value); + // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value); @@ -4752,6 +4791,10 @@ class ExternalDoubleArray: public ExternalArray { MUST_USE_RESULT inline MaybeObject* get(int index); inline void set(int index, double value); + static Handle SetValue(Handle array, + uint32_t index, + Handle value); + // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. MUST_USE_RESULT MaybeObject* SetValue(uint32_t index, Object* value); @@ -9752,6 +9795,10 @@ class JSArray: public JSObject { // is set to a smi. This matches the set function on FixedArray. inline void set_length(Smi* length); + static void JSArrayUpdateLengthFromIndex(Handle array, + uint32_t index, + Handle value); + MUST_USE_RESULT MaybeObject* JSArrayUpdateLengthFromIndex(uint32_t index, Object* value); diff --git a/src/runtime.cc b/src/runtime.cc index 9df3ff8..2cf033c 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -9821,22 +9821,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInOldDataSpace) { // array. Returns true if the element was pushed on the stack and // false otherwise. RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) { - SealHandleScope shs(isolate); + HandleScope scope(isolate); ASSERT(args.length() == 2); - CONVERT_ARG_CHECKED(JSArray, array, 0); - CONVERT_ARG_CHECKED(JSReceiver, element, 1); + CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); + CONVERT_ARG_HANDLE_CHECKED(JSReceiver, element, 1); RUNTIME_ASSERT(array->HasFastSmiOrObjectElements()); int length = Smi::cast(array->length())->value(); FixedArray* elements = FixedArray::cast(array->elements()); for (int i = 0; i < length; i++) { - if (elements->get(i) == element) return isolate->heap()->false_value(); + if (elements->get(i) == *element) return isolate->heap()->false_value(); } - Object* obj; + // Strict not needed. Used for cycle detection in Array join implementation. - { MaybeObject* maybe_obj = - array->SetFastElement(length, element, kNonStrictMode, true); - if (!maybe_obj->ToObject(&obj)) return maybe_obj; - } + RETURN_IF_EMPTY_HANDLE(isolate, JSObject::SetFastElement(array, length, + element, + kNonStrictMode, + true)); return isolate->heap()->true_value(); } diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index 554bab4..799146e 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -760,7 +760,7 @@ TEST(JSArray) { CHECK(array->HasFastSmiOrObjectElements()); // array[length] = name. - array->SetElement(0, *name, NONE, kNonStrictMode)->ToObjectChecked(); + JSReceiver::SetElement(array, 0, name, NONE, kNonStrictMode); CHECK_EQ(Smi::FromInt(1), array->length()); CHECK_EQ(array->GetElement(isolate, 0), *name); @@ -775,7 +775,7 @@ TEST(JSArray) { CHECK(array->HasDictionaryElements()); // Must be in slow mode. // array[length] = name. - array->SetElement(int_length, *name, NONE, kNonStrictMode)->ToObjectChecked(); + JSReceiver::SetElement(array, int_length, name, NONE, kNonStrictMode); uint32_t new_int_length = 0; CHECK(array->length()->ToArrayIndex(&new_int_length)); CHECK_EQ(static_cast(int_length), new_int_length - 1); @@ -805,8 +805,8 @@ TEST(JSObjectCopy) { JSReceiver::SetProperty(obj, first, one, NONE, kNonStrictMode); JSReceiver::SetProperty(obj, second, two, NONE, kNonStrictMode); - obj->SetElement(0, *first, NONE, kNonStrictMode)->ToObjectChecked(); - obj->SetElement(1, *second, NONE, kNonStrictMode)->ToObjectChecked(); + JSReceiver::SetElement(obj, 0, first, NONE, kNonStrictMode); + JSReceiver::SetElement(obj, 1, second, NONE, kNonStrictMode); // Make the clone. Handle clone = JSObject::Copy(obj); @@ -822,8 +822,8 @@ TEST(JSObjectCopy) { JSReceiver::SetProperty(clone, first, two, NONE, kNonStrictMode); JSReceiver::SetProperty(clone, second, one, NONE, kNonStrictMode); - clone->SetElement(0, *second, NONE, kNonStrictMode)->ToObjectChecked(); - clone->SetElement(1, *first, NONE, kNonStrictMode)->ToObjectChecked(); + JSReceiver::SetElement(clone, 0, second, NONE, kNonStrictMode); + JSReceiver::SetElement(clone, 1, first, NONE, kNonStrictMode); CHECK_EQ(obj->GetElement(isolate, 1), clone->GetElement(isolate, 0)); CHECK_EQ(obj->GetElement(isolate, 0), clone->GetElement(isolate, 1)); -- 2.7.4