From: mstarzinger@chromium.org Date: Tue, 17 Sep 2013 11:01:43 +0000 (+0000) Subject: Handlify JSReceiver::SetProperty and friends. X-Git-Tag: upstream/4.7.83~12464 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=16a22a96c3582d6186e4fc53b75bb422b1bd2ba0;p=platform%2Fupstream%2Fv8.git Handlify JSReceiver::SetProperty and friends. R=verwaest@chromium.org Review URL: https://codereview.chromium.org/23601031 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16758 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/ic.cc b/src/ic.cc index 5267af1..992df1b 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -1670,8 +1670,10 @@ MaybeObject* StoreIC::Store(State state, JSReceiver::StoreFromKeyed store_mode) { // Handle proxies. if (object->IsJSProxy()) { - return JSReceiver::SetPropertyOrFail( + Handle result = JSReceiver::SetProperty( Handle::cast(object), name, value, NONE, strict_mode); + RETURN_IF_EMPTY_HANDLE(isolate(), result); + return *result; } // If the object is undefined or null it's illegal to try to set any @@ -1709,8 +1711,10 @@ MaybeObject* StoreIC::Store(State state, // Observed objects are always modified through the runtime. if (FLAG_harmony_observation && receiver->map()->is_observed()) { - return JSReceiver::SetPropertyOrFail( + Handle result = JSReceiver::SetProperty( receiver, name, value, NONE, strict_mode, store_mode); + RETURN_IF_EMPTY_HANDLE(isolate(), result); + return *result; } // Use specialized code for setting the length of arrays with fast @@ -1727,8 +1731,10 @@ MaybeObject* StoreIC::Store(State state, StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate()); set_target(*stub); TRACE_IC("StoreIC", name, state, *stub); - return JSReceiver::SetPropertyOrFail( + Handle result = JSReceiver::SetProperty( receiver, name, value, NONE, strict_mode, store_mode); + RETURN_IF_EMPTY_HANDLE(isolate(), result); + return *result; } if (receiver->IsJSGlobalProxy()) { @@ -1741,8 +1747,10 @@ MaybeObject* StoreIC::Store(State state, set_target(*stub); TRACE_IC("StoreIC", name, state, *stub); } - return JSReceiver::SetPropertyOrFail( + Handle result = JSReceiver::SetProperty( receiver, name, value, NONE, strict_mode, store_mode); + RETURN_IF_EMPTY_HANDLE(isolate(), result); + return *result; } LookupResult lookup(isolate()); @@ -1773,8 +1781,10 @@ MaybeObject* StoreIC::Store(State state, } // Set the property. - return JSReceiver::SetPropertyOrFail( + Handle result = JSReceiver::SetProperty( receiver, name, value, NONE, strict_mode, store_mode); + RETURN_IF_EMPTY_HANDLE(isolate(), result); + return *result; } diff --git a/src/objects-inl.h b/src/objects-inl.h index 89abe50..08ef1cf 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -1566,21 +1566,6 @@ MaybeObject* JSObject::AllocateStorageForMap(Map* map) { } -MaybeObject* JSObject::MigrateInstance() { - // Converting any field to the most specific type will cause the - // GeneralizeFieldRepresentation algorithm to create the most general existing - // transition that matches the object. This achieves what is needed. - Map* original_map = map(); - MaybeObject* maybe_result = GeneralizeFieldRepresentation( - 0, Representation::None(), ALLOW_AS_CONSTANT); - JSObject* result; - if (FLAG_trace_migration && maybe_result->To(&result)) { - PrintInstanceMigration(stdout, original_map, result->map()); - } - return maybe_result; -} - - MaybeObject* JSObject::TryMigrateInstance() { Map* new_map = map()->CurrentMapForDeprecated(); if (new_map == NULL) return Smi::FromInt(0); diff --git a/src/objects.cc b/src/objects.cc index bddc5d7..ae726fd 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -455,10 +455,8 @@ Handle JSProxy::SetElementWithHandler(Handle proxy, StrictModeFlag strict_mode) { Isolate* isolate = proxy->GetIsolate(); Handle name = isolate->factory()->Uint32ToString(index); - CALL_HEAP_FUNCTION(isolate, - proxy->SetPropertyWithHandler( - *receiver, *name, *value, NONE, strict_mode), - Object); + return SetPropertyWithHandler( + proxy, receiver, name, value, NONE, strict_mode); } @@ -1871,6 +1869,20 @@ String* JSReceiver::constructor_name() { } +Handle JSObject::AddFastPropertyUsingMap( + Handle object, + Handle new_map, + Handle name, + Handle value, + int field_index, + Representation representation) { + CALL_HEAP_FUNCTION(object->GetIsolate(), + object->AddFastPropertyUsingMap( + *new_map, *name, *value, field_index, representation), + Object); +} + + MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, Name* name, Object* value, @@ -1900,182 +1912,215 @@ MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, } -MaybeObject* JSObject::AddFastProperty(Name* name, - Object* value, - PropertyAttributes attributes, - StoreFromKeyed store_mode, - ValueType value_type, - TransitionFlag flag) { - ASSERT(!IsJSGlobalProxy()); +static MaybeObject* CopyAddFieldDescriptor(Map* map, + Name* name, + int index, + PropertyAttributes attributes, + Representation representation, + TransitionFlag flag) { + Map* new_map; + FieldDescriptor new_field_desc(name, index, attributes, representation); + MaybeObject* maybe_map = map->CopyAddDescriptor(&new_field_desc, flag); + if (!maybe_map->To(&new_map)) return maybe_map; + int unused_property_fields = map->unused_property_fields() - 1; + if (unused_property_fields < 0) { + unused_property_fields += JSObject::kFieldsAdded; + } + new_map->set_unused_property_fields(unused_property_fields); + return new_map; +} + + +static Handle CopyAddFieldDescriptor(Handle map, + Handle name, + int index, + PropertyAttributes attributes, + Representation representation, + TransitionFlag flag) { + CALL_HEAP_FUNCTION(map->GetIsolate(), + CopyAddFieldDescriptor( + *map, *name, index, attributes, representation, flag), + Map); +} + + +void JSObject::AddFastProperty(Handle object, + Handle name, + Handle value, + PropertyAttributes attributes, + StoreFromKeyed store_mode, + ValueType value_type, + TransitionFlag flag) { + ASSERT(!object->IsJSGlobalProxy()); ASSERT(DescriptorArray::kNotFound == - map()->instance_descriptors()->Search( - name, map()->NumberOfOwnDescriptors())); + object->map()->instance_descriptors()->Search( + *name, object->map()->NumberOfOwnDescriptors())); // Normalize the object if the name is an actual name (not the // hidden strings) and is not a real identifier. // Normalize the object if it will have too many fast properties. - Isolate* isolate = GetHeap()->isolate(); - if (!name->IsCacheable(isolate) || TooManyFastProperties(store_mode)) { - MaybeObject* maybe_failure = - NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); - if (maybe_failure->IsFailure()) return maybe_failure; - return AddSlowProperty(name, value, attributes); + Isolate* isolate = object->GetIsolate(); + if (!name->IsCacheable(isolate) || + object->TooManyFastProperties(store_mode)) { + NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); + AddSlowProperty(object, name, value, attributes); + return; } // Compute the new index for new field. - int index = map()->NextFreePropertyIndex(); + int index = object->map()->NextFreePropertyIndex(); // Allocate new instance descriptors with (name, index) added - if (IsJSContextExtensionObject()) value_type = FORCE_TAGGED; + if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED; Representation representation = value->OptimalRepresentation(value_type); + Handle new_map = CopyAddFieldDescriptor( + handle(object->map()), name, index, attributes, representation, flag); - FieldDescriptor new_field(name, index, attributes, representation); + AddFastPropertyUsingMap(object, new_map, name, value, index, representation); +} - Map* new_map; - MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&new_field, flag); - if (!maybe_new_map->To(&new_map)) return maybe_new_map; - int unused_property_fields = map()->unused_property_fields() - 1; - if (unused_property_fields < 0) { - unused_property_fields += kFieldsAdded; - } - new_map->set_unused_property_fields(unused_property_fields); - - return AddFastPropertyUsingMap(new_map, name, value, index, representation); +static MaybeObject* CopyAddConstantDescriptor(Map* map, + Name* name, + Object* value, + PropertyAttributes attributes, + TransitionFlag flag) { + ConstantDescriptor new_constant_desc(name, value, attributes); + return map->CopyAddDescriptor(&new_constant_desc, flag); } -MaybeObject* JSObject::AddConstantProperty( - Name* name, - Object* constant, - PropertyAttributes attributes, - TransitionFlag initial_flag) { - // Allocate new instance descriptors with (name, constant) added - ConstantDescriptor d(name, constant, attributes); +static Handle CopyAddConstantDescriptor(Handle map, + Handle name, + Handle value, + PropertyAttributes attributes, + TransitionFlag flag) { + CALL_HEAP_FUNCTION(map->GetIsolate(), + CopyAddConstantDescriptor( + *map, *name, *value, attributes, flag), + Map); +} + +void JSObject::AddConstantProperty(Handle object, + Handle name, + Handle constant, + PropertyAttributes attributes, + TransitionFlag initial_flag) { TransitionFlag flag = // Do not add transitions to global objects. - (IsGlobalObject() || + (object->IsGlobalObject() || // Don't add transitions to special properties with non-trivial // attributes. attributes != NONE) ? OMIT_TRANSITION : initial_flag; - Map* new_map; - MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag); - if (!maybe_new_map->To(&new_map)) return maybe_new_map; + // Allocate new instance descriptors with (name, constant) added. + Handle new_map = CopyAddConstantDescriptor( + handle(object->map()), name, constant, attributes, flag); - set_map(new_map); - return constant; + object->set_map(*new_map); } -// Add property in slow mode -MaybeObject* JSObject::AddSlowProperty(Name* name, - Object* value, - PropertyAttributes attributes) { - ASSERT(!HasFastProperties()); - NameDictionary* dict = property_dictionary(); - Object* store_value = value; - if (IsGlobalObject()) { +// TODO(mstarzinger): Temporary wrapper until handlified. +static Handle NameDictionaryAdd(Handle dict, + Handle name, + Handle value, + PropertyDetails details) { + CALL_HEAP_FUNCTION(dict->GetIsolate(), + dict->Add(*name, *value, details), + NameDictionary); +} + + +void JSObject::AddSlowProperty(Handle object, + Handle name, + Handle value, + PropertyAttributes attributes) { + ASSERT(!object->HasFastProperties()); + Isolate* isolate = object->GetIsolate(); + Handle dict(object->property_dictionary()); + if (object->IsGlobalObject()) { // In case name is an orphaned property reuse the cell. - int entry = dict->FindEntry(name); + int entry = dict->FindEntry(*name); if (entry != NameDictionary::kNotFound) { - store_value = dict->ValueAt(entry); - MaybeObject* maybe_type = - PropertyCell::cast(store_value)->SetValueInferType(value); - if (maybe_type->IsFailure()) return maybe_type; + Handle cell(PropertyCell::cast(dict->ValueAt(entry))); + PropertyCell::SetValueInferType(cell, value); // Assign an enumeration index to the property and update // SetNextEnumerationIndex. int index = dict->NextEnumerationIndex(); PropertyDetails details = PropertyDetails(attributes, NORMAL, index); dict->SetNextEnumerationIndex(index + 1); - dict->SetEntry(entry, name, store_value, details); - return value; - } - Heap* heap = GetHeap(); - { MaybeObject* maybe_store_value = - heap->AllocatePropertyCell(value); - if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; + dict->SetEntry(entry, *name, *cell, details); + return; } - MaybeObject* maybe_type = - PropertyCell::cast(store_value)->SetValueInferType(value); - if (maybe_type->IsFailure()) return maybe_type; + Handle cell = isolate->factory()->NewPropertyCell(value); + PropertyCell::SetValueInferType(cell, value); + value = cell; } PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); - Object* result; - { MaybeObject* maybe_result = dict->Add(name, store_value, details); - if (!maybe_result->ToObject(&result)) return maybe_result; - } - if (dict != result) set_properties(NameDictionary::cast(result)); - return value; + Handle result = NameDictionaryAdd(dict, name, value, details); + if (*dict != *result) object->set_properties(*result); } -MaybeObject* JSObject::AddProperty(Name* name, - Object* value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - JSReceiver::StoreFromKeyed store_mode, - ExtensibilityCheck extensibility_check, - ValueType value_type, - StoreMode mode, - TransitionFlag transition_flag) { - ASSERT(!IsJSGlobalProxy()); - Map* map_of_this = map(); - Heap* heap = GetHeap(); - Isolate* isolate = heap->isolate(); - MaybeObject* result; +Handle JSObject::AddProperty(Handle object, + Handle name, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode, + JSReceiver::StoreFromKeyed store_mode, + ExtensibilityCheck extensibility_check, + ValueType value_type, + StoreMode mode, + TransitionFlag transition_flag) { + ASSERT(!object->IsJSGlobalProxy()); + Isolate* isolate = object->GetIsolate(); if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && - !map_of_this->is_extensible()) { + !object->map()->is_extensible()) { if (strict_mode == kNonStrictMode) { return value; } else { - Handle args[1] = {Handle(name)}; - return isolate->Throw( - *isolate->factory()->NewTypeError("object_not_extensible", - HandleVector(args, 1))); + Handle args[1] = { name }; + Handle error = isolate->factory()->NewTypeError( + "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); + isolate->Throw(*error); + return Handle(); } } - if (HasFastProperties()) { + if (object->HasFastProperties()) { // Ensure the descriptor array does not get too big. - if (map_of_this->NumberOfOwnDescriptors() < + if (object->map()->NumberOfOwnDescriptors() < DescriptorArray::kMaxNumberOfDescriptors) { // TODO(verwaest): Support other constants. // if (mode == ALLOW_AS_CONSTANT && // !value->IsTheHole() && // !value->IsConsString()) { if (value->IsJSFunction()) { - result = AddConstantProperty(name, value, attributes, transition_flag); + AddConstantProperty(object, name, value, attributes, transition_flag); } else { - result = AddFastProperty( - name, value, attributes, store_mode, value_type, transition_flag); + AddFastProperty(object, name, value, attributes, store_mode, + value_type, transition_flag); } } else { // Normalize the object to prevent very large instance descriptors. // This eliminates unwanted N^2 allocation and lookup behavior. - Object* obj; - MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); - if (!maybe->To(&obj)) return maybe; - result = AddSlowProperty(name, value, attributes); + NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); + AddSlowProperty(object, name, value, attributes); } } else { - result = AddSlowProperty(name, value, attributes); + AddSlowProperty(object, name, value, attributes); } - Handle hresult; - if (!result->ToHandle(&hresult, isolate)) return result; - - if (FLAG_harmony_observation && map()->is_observed()) { - EnqueueChangeRecord(handle(this, isolate), - "new", - handle(name, isolate), - handle(heap->the_hole_value(), isolate)); + if (FLAG_harmony_observation && object->map()->is_observed()) { + Handle old_value = isolate->factory()->the_hole_value(); + EnqueueChangeRecord(object, "new", name, old_value); } - return *hresult; + return value; } @@ -2115,37 +2160,39 @@ void JSObject::DeliverChangeRecords(Isolate* isolate) { } -MaybeObject* JSObject::SetPropertyPostInterceptor( - Name* name, - Object* value, +Handle JSObject::SetPropertyPostInterceptor( + Handle object, + Handle name, + Handle value, PropertyAttributes attributes, - StrictModeFlag strict_mode, - StoreMode mode) { + StrictModeFlag strict_mode) { // Check local property, ignore interceptor. - LookupResult result(GetIsolate()); - LocalLookupRealNamedProperty(name, &result); - if (!result.IsFound()) map()->LookupTransition(this, name, &result); + LookupResult result(object->GetIsolate()); + object->LocalLookupRealNamedProperty(*name, &result); + if (!result.IsFound()) { + object->map()->LookupTransition(*object, *name, &result); + } if (result.IsFound()) { // An existing property or a map transition was found. Use set property to // handle all these cases. - return SetProperty(&result, name, value, attributes, strict_mode); + return SetPropertyForResult(object, &result, name, value, attributes, + strict_mode, MAY_BE_STORE_FROM_KEYED); } bool done = false; - MaybeObject* result_object = - SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done); + Handle result_object = SetPropertyViaPrototypes( + object, name, value, attributes, strict_mode, &done); if (done) return result_object; // Add a new real property. - return AddProperty(name, value, attributes, strict_mode, - MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, - OPTIMAL_REPRESENTATION, mode); + return AddProperty(object, name, value, attributes, strict_mode); } -MaybeObject* JSObject::ReplaceSlowProperty(Name* name, - Object* value, - PropertyAttributes attributes) { - NameDictionary* dictionary = property_dictionary(); - int old_index = dictionary->FindEntry(name); +static Handle ReplaceSlowProperty(Handle object, + Handle name, + Handle value, + PropertyAttributes attributes) { + NameDictionary* dictionary = object->property_dictionary(); + int old_index = dictionary->FindEntry(*name); int new_enumeration_index = 0; // 0 means "Use the next available index." if (old_index != -1) { // All calls to ReplaceSlowProperty have had all transitions removed. @@ -2153,7 +2200,7 @@ MaybeObject* JSObject::ReplaceSlowProperty(Name* name, } PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); - return SetNormalizedProperty(name, value, new_details); + return JSObject::SetNormalizedProperty(object, name, value, new_details); } @@ -2260,6 +2307,11 @@ bool Map::InstancesNeedRewriting(Map* target, } +void JSObject::MigrateToMap(Handle object, Handle new_map) { + CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), object->MigrateToMap(*new_map)); +} + + // To migrate an instance to a map: // - First check whether the instance needs to be rewritten. If not, simply // change the map. @@ -2361,17 +2413,14 @@ MaybeObject* JSObject::MigrateToMap(Map* new_map) { } -MaybeObject* JSObject::GeneralizeFieldRepresentation( - int modify_index, - Representation new_representation, - StoreMode store_mode) { - Map* new_map; - MaybeObject* maybe_new_map = map()->GeneralizeRepresentation( - modify_index, new_representation, store_mode); - if (!maybe_new_map->To(&new_map)) return maybe_new_map; - if (map() == new_map) return this; - - return MigrateToMap(new_map); +void JSObject::GeneralizeFieldRepresentation(Handle object, + int modify_index, + Representation new_representation, + StoreMode store_mode) { + Handle new_map = Map::GeneralizeRepresentation( + handle(object->map()), modify_index, new_representation, store_mode); + if (object->map() == *new_map) return; + return MigrateToMap(object, new_map); } @@ -2385,14 +2434,12 @@ int Map::NumberOfFields() { } -MaybeObject* Map::CopyGeneralizeAllRepresentations( - int modify_index, - StoreMode store_mode, - PropertyAttributes attributes, - const char* reason) { - Map* new_map; - MaybeObject* maybe_map = this->Copy(); - if (!maybe_map->To(&new_map)) return maybe_map; +Handle Map::CopyGeneralizeAllRepresentations(Handle map, + int modify_index, + StoreMode store_mode, + PropertyAttributes attributes, + const char* reason) { + Handle new_map = Copy(map); DescriptorArray* descriptors = new_map->instance_descriptors(); descriptors->InitializeRepresentations(Representation::Tagged()); @@ -2414,7 +2461,7 @@ MaybeObject* Map::CopyGeneralizeAllRepresentations( } if (FLAG_trace_generalization) { - PrintGeneralization(stdout, reason, modify_index, + map->PrintGeneralization(stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(), new_map->NumberOfOwnDescriptors(), details.type() == CONSTANT && store_mode == FORCE_FIELD, @@ -2562,11 +2609,11 @@ Map* Map::FindLastMatchMap(int verbatim, // - If |updated| == |split_map|, |updated| is in the expected state. Return it. // - Otherwise, invalidate the outdated transition target from |updated|, and // replace its transition tree with a new branch for the updated descriptors. -MaybeObject* Map::GeneralizeRepresentation(int modify_index, - Representation new_representation, - StoreMode store_mode) { - Map* old_map = this; - DescriptorArray* old_descriptors = old_map->instance_descriptors(); +Handle Map::GeneralizeRepresentation(Handle old_map, + int modify_index, + Representation new_representation, + StoreMode store_mode) { + Handle old_descriptors(old_map->instance_descriptors()); PropertyDetails old_details = old_descriptors->GetDetails(modify_index); Representation old_representation = old_details.representation(); @@ -2582,37 +2629,37 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index, } int descriptors = old_map->NumberOfOwnDescriptors(); - Map* root_map = old_map->FindRootMap(); + Handle root_map(old_map->FindRootMap()); // Check the state of the root map. - if (!old_map->EquivalentToForTransition(root_map)) { - return CopyGeneralizeAllRepresentations( - modify_index, store_mode, old_details.attributes(), "not equivalent"); + if (!old_map->EquivalentToForTransition(*root_map)) { + return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, + old_details.attributes(), "not equivalent"); } int verbatim = root_map->NumberOfOwnDescriptors(); if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { - return CopyGeneralizeAllRepresentations( - modify_index, store_mode, + return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, old_details.attributes(), "root modification"); } - Map* updated = root_map->FindUpdatedMap( - verbatim, descriptors, old_descriptors); - if (updated == NULL) { - return CopyGeneralizeAllRepresentations( - modify_index, store_mode, old_details.attributes(), "incompatible"); + Map* raw_updated = root_map->FindUpdatedMap( + verbatim, descriptors, *old_descriptors); + if (raw_updated == NULL) { + return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, + old_details.attributes(), "incompatible"); } - DescriptorArray* updated_descriptors = updated->instance_descriptors(); + Handle updated(raw_updated); + Handle updated_descriptors(updated->instance_descriptors()); int valid = updated->NumberOfOwnDescriptors(); // Directly change the map if the target map is more general. Ensure that the // target type of the modify_index is a FIELD, unless we are migrating. if (updated_descriptors->IsMoreGeneralThan( - verbatim, valid, descriptors, old_descriptors) && + verbatim, valid, descriptors, *old_descriptors) && (store_mode == ALLOW_AS_CONSTANT || updated_descriptors->GetDetails(modify_index).type() == FIELD)) { Representation updated_representation = @@ -2620,10 +2667,9 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index, if (new_representation.fits_into(updated_representation)) return updated; } - DescriptorArray* new_descriptors; - MaybeObject* maybe_descriptors = updated_descriptors->Merge( - verbatim, valid, descriptors, modify_index, store_mode, old_descriptors); - if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; + Handle new_descriptors = DescriptorArray::Merge( + updated_descriptors, verbatim, valid, descriptors, modify_index, + store_mode, old_descriptors); ASSERT(store_mode == ALLOW_AS_CONSTANT || new_descriptors->GetDetails(modify_index).type() == FIELD); @@ -2635,8 +2681,8 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index, new_descriptors->SetRepresentation(modify_index, updated_representation); } - Map* split_map = root_map->FindLastMatchMap( - verbatim, descriptors, new_descriptors); + Handle split_map(root_map->FindLastMatchMap( + verbatim, descriptors, *new_descriptors)); int split_descriptors = split_map->NumberOfOwnDescriptors(); // This is shadowed by |updated_descriptors| being more general than @@ -2645,28 +2691,20 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index, int descriptor = split_descriptors; split_map->DeprecateTarget( - old_descriptors->GetKey(descriptor), new_descriptors); + old_descriptors->GetKey(descriptor), *new_descriptors); if (FLAG_trace_generalization) { - PrintGeneralization( + old_map->PrintGeneralization( stdout, "", modify_index, descriptor, descriptors, old_descriptors->GetDetails(modify_index).type() == CONSTANT && store_mode == FORCE_FIELD, old_representation, updated_representation); } - Map* new_map = split_map; // Add missing transitions. + Handle new_map = split_map; for (; descriptor < descriptors; descriptor++) { - MaybeObject* maybe_map = new_map->CopyInstallDescriptors( - descriptor, new_descriptors); - if (!maybe_map->To(&new_map)) { - // Create a handle for the last created map to ensure it stays alive - // during GC. Its descriptor array is too large, but it will be - // overwritten during retry anyway. - Handle(new_map); - return maybe_map; - } + new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors); new_map->set_migration_target(true); } @@ -2703,79 +2741,52 @@ Map* Map::CurrentMapForDeprecated() { } -MaybeObject* JSObject::SetPropertyWithInterceptor( - Name* name, - Object* value, +Handle JSObject::SetPropertyWithInterceptor( + Handle object, + Handle name, + Handle value, PropertyAttributes attributes, StrictModeFlag strict_mode) { // TODO(rossberg): Support symbols in the API. if (name->IsSymbol()) return value; - Isolate* isolate = GetIsolate(); - HandleScope scope(isolate); - Handle this_handle(this); - Handle name_handle(String::cast(name)); - Handle value_handle(value, isolate); - Handle interceptor(GetNamedInterceptor()); + Isolate* isolate = object->GetIsolate(); + Handle name_string = Handle::cast(name); + Handle interceptor(object->GetNamedInterceptor()); if (!interceptor->setter()->IsUndefined()) { - LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name)); - PropertyCallbackArguments args(isolate, interceptor->data(), this, this); + LOG(isolate, + ApiNamedPropertyAccess("interceptor-named-set", *object, *name)); + PropertyCallbackArguments args( + isolate, interceptor->data(), *object, *object); v8::NamedPropertySetterCallback setter = v8::ToCData(interceptor->setter()); - Handle value_unhole(value->IsTheHole() ? - isolate->heap()->undefined_value() : - value, - isolate); + Handle value_unhole = value->IsTheHole() + ? Handle(isolate->factory()->undefined_value()) : value; v8::Handle result = args.Call(setter, - v8::Utils::ToLocal(name_handle), + v8::Utils::ToLocal(name_string), v8::Utils::ToLocal(value_unhole)); - RETURN_IF_SCHEDULED_EXCEPTION(isolate); - if (!result.IsEmpty()) return *value_handle; + RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); + if (!result.IsEmpty()) return value; } - MaybeObject* raw_result = - this_handle->SetPropertyPostInterceptor(*name_handle, - *value_handle, - attributes, - strict_mode); - RETURN_IF_SCHEDULED_EXCEPTION(isolate); - return raw_result; + Handle result = + SetPropertyPostInterceptor(object, name, value, attributes, strict_mode); + RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); + return result; } Handle JSReceiver::SetProperty(Handle object, - Handle key, + Handle name, Handle value, PropertyAttributes attributes, - StrictModeFlag strict_mode) { - CALL_HEAP_FUNCTION(object->GetIsolate(), - object->SetProperty(*key, *value, attributes, strict_mode), - Object); -} - - -MaybeObject* JSReceiver::SetPropertyOrFail( - Handle object, - Handle key, - Handle value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - JSReceiver::StoreFromKeyed store_mode) { - CALL_HEAP_FUNCTION_PASS_EXCEPTION( - object->GetIsolate(), - object->SetProperty(*key, *value, attributes, strict_mode, store_mode)); -} - - -MaybeObject* JSReceiver::SetProperty(Name* name, - Object* value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - JSReceiver::StoreFromKeyed store_mode) { - LookupResult result(GetIsolate()); - LocalLookup(name, &result, true); + StrictModeFlag strict_mode, + StoreFromKeyed store_mode) { + LookupResult result(object->GetIsolate()); + object->LocalLookup(*name, &result, true); if (!result.IsFound()) { - map()->LookupTransition(JSObject::cast(this), name, &result); + object->map()->LookupTransition(JSObject::cast(*object), *name, &result); } - return SetProperty(&result, name, value, attributes, strict_mode, store_mode); + return SetProperty(object, &result, name, value, attributes, strict_mode, + store_mode); } @@ -2930,21 +2941,20 @@ MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( return heap->the_hole_value(); } -MaybeObject* JSObject::SetPropertyViaPrototypes( - Name* name, - Object* value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - bool* done) { - Heap* heap = GetHeap(); - Isolate* isolate = heap->isolate(); +Handle JSObject::SetPropertyViaPrototypes(Handle object, + Handle name, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode, + bool* done) { + Isolate* isolate = object->GetIsolate(); *done = false; // We could not find a local property so let's check whether there is an // accessor that wants to handle the property, or whether the property is // read-only on the prototype chain. LookupResult result(isolate); - LookupRealNamedPropertyInPrototypes(name, &result); + object->LookupRealNamedPropertyInPrototypes(*name, &result); if (result.IsFound()) { switch (result.type()) { case NORMAL: @@ -2955,19 +2965,25 @@ MaybeObject* JSObject::SetPropertyViaPrototypes( case INTERCEPTOR: { PropertyAttributes attr = result.holder()->GetPropertyAttributeWithInterceptor( - this, name, true); + *object, *name, true); *done = !!(attr & READ_ONLY); break; } case CALLBACKS: { if (!FLAG_es5_readonly && result.IsReadOnly()) break; *done = true; - return SetPropertyWithCallback(result.GetCallbackObject(), - name, value, result.holder(), strict_mode); + CALL_HEAP_FUNCTION(isolate, + object->SetPropertyWithCallback( + result.GetCallbackObject(), + *name, *value, result.holder(), strict_mode), + Object); } case HANDLER: { - return result.proxy()->SetPropertyViaPrototypesWithHandler( - this, name, value, attributes, strict_mode, done); + CALL_HEAP_FUNCTION(isolate, + result.proxy()->SetPropertyViaPrototypesWithHandler( + *object, *name, *value, attributes, strict_mode, + done), + Object); } case TRANSITION: case NONEXISTENT: @@ -2980,12 +2996,13 @@ MaybeObject* JSObject::SetPropertyViaPrototypes( if (!FLAG_es5_readonly) *done = false; if (*done) { if (strict_mode == kNonStrictMode) return value; - Handle args[] = { Handle(name, isolate), - Handle(this, isolate)}; - return isolate->Throw(*isolate->factory()->NewTypeError( - "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); + Handle args[] = { name, object }; + Handle error = isolate->factory()->NewTypeError( + "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); + isolate->Throw(*error); + return Handle(); } - return heap->the_hole_value(); + return isolate->factory()->the_hole_value(); } @@ -3406,17 +3423,18 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck( } -MaybeObject* JSReceiver::SetProperty(LookupResult* result, - Name* key, - Object* value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - JSReceiver::StoreFromKeyed store_mode) { +Handle JSReceiver::SetProperty(Handle object, + LookupResult* result, + Handle key, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode, + StoreFromKeyed store_mode) { if (result->IsHandler()) { - return result->proxy()->SetPropertyWithHandler( - this, key, value, attributes, strict_mode); + return JSProxy::SetPropertyWithHandler(handle(result->proxy()), + object, key, value, attributes, strict_mode); } else { - return JSObject::cast(this)->SetPropertyForResult( + return JSObject::SetPropertyForResult(Handle::cast(object), result, key, value, attributes, strict_mode, store_mode); } } @@ -3440,26 +3458,22 @@ bool JSProxy::HasPropertyWithHandler(Name* name_raw) { } -MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler( - JSReceiver* receiver_raw, - Name* name_raw, - Object* value_raw, - PropertyAttributes attributes, - StrictModeFlag strict_mode) { - Isolate* isolate = GetIsolate(); - HandleScope scope(isolate); - Handle receiver(receiver_raw); - Handle name(name_raw, isolate); - Handle value(value_raw, isolate); +Handle JSProxy::SetPropertyWithHandler(Handle proxy, + Handle receiver, + Handle name, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode) { + Isolate* isolate = proxy->GetIsolate(); // TODO(rossberg): adjust once there is a story for symbols vs proxies. - if (name->IsSymbol()) return *value; + if (name->IsSymbol()) return value; Handle args[] = { receiver, name, value }; - CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args); - if (isolate->has_pending_exception()) return Failure::Exception(); + proxy->CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args); + if (isolate->has_pending_exception()) return Handle(); - return *value; + return value; } @@ -3734,36 +3748,31 @@ void JSObject::AllocateStorageForMap(Handle object, Handle map) { void JSObject::MigrateInstance(Handle object) { - CALL_HEAP_FUNCTION_VOID( - object->GetIsolate(), - object->MigrateInstance()); + // Converting any field to the most specific type will cause the + // GeneralizeFieldRepresentation algorithm to create the most general existing + // transition that matches the object. This achieves what is needed. + Handle original_map(object->map()); + GeneralizeFieldRepresentation( + object, 0, Representation::None(), ALLOW_AS_CONSTANT); + if (FLAG_trace_migration) { + object->PrintInstanceMigration(stdout, *original_map, object->map()); + } } Handle JSObject::TryMigrateInstance(Handle object) { - CALL_HEAP_FUNCTION( - object->GetIsolate(), - object->MigrateInstance(), - Object); -} - - -Handle Map::GeneralizeRepresentation(Handle map, - int modify_index, - Representation representation, - StoreMode store_mode) { - CALL_HEAP_FUNCTION( - map->GetIsolate(), - map->GeneralizeRepresentation(modify_index, representation, store_mode), - Map); + MigrateInstance(object); + return object; } -static MaybeObject* SetPropertyUsingTransition(LookupResult* lookup, - Handle name, - Handle value, - PropertyAttributes attributes) { - Map* transition_map = lookup->GetTransitionTarget(); +Handle JSObject::SetPropertyUsingTransition( + Handle object, + LookupResult* lookup, + Handle name, + Handle value, + PropertyAttributes attributes) { + Handle transition_map(lookup->GetTransitionTarget()); int descriptor = transition_map->LastAdded(); DescriptorArray* descriptors = transition_map->instance_descriptors(); @@ -3773,8 +3782,8 @@ static MaybeObject* SetPropertyUsingTransition(LookupResult* lookup, // AddProperty will either normalize the object, or create a new fast copy // of the map. If we get a fast copy of the map, all field representations // will be tagged since the transition is omitted. - return lookup->holder()->AddProperty( - *name, *value, attributes, kNonStrictMode, + return JSObject::AddProperty( + object, name, value, attributes, kNonStrictMode, JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, JSReceiver::OMIT_EXTENSIBILITY_CHECK, JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); @@ -3785,45 +3794,40 @@ static MaybeObject* SetPropertyUsingTransition(LookupResult* lookup, // (value->IsUninitialized) as constant. if (details.type() == CONSTANT && descriptors->GetValue(descriptor) == *value) { - lookup->holder()->set_map(transition_map); - return *value; + object->set_map(*transition_map); + return value; } Representation representation = details.representation(); if (!value->FitsRepresentation(representation) || details.type() == CONSTANT) { - MaybeObject* maybe_map = transition_map->GeneralizeRepresentation( + transition_map = Map::GeneralizeRepresentation(transition_map, descriptor, value->OptimalRepresentation(), FORCE_FIELD); - if (!maybe_map->To(&transition_map)) return maybe_map; Object* back = transition_map->GetBackPointer(); if (back->IsMap()) { - MaybeObject* maybe_failure = - lookup->holder()->MigrateToMap(Map::cast(back)); - if (maybe_failure->IsFailure()) return maybe_failure; + MigrateToMap(object, handle(Map::cast(back))); } descriptors = transition_map->instance_descriptors(); representation = descriptors->GetDetails(descriptor).representation(); } int field_index = descriptors->GetFieldIndex(descriptor); - return lookup->holder()->AddFastPropertyUsingMap( - transition_map, *name, *value, field_index, representation); + return AddFastPropertyUsingMap( + object, transition_map, name, value, field_index, representation); } -static MaybeObject* SetPropertyToField(LookupResult* lookup, - Handle name, - Handle value) { +static Handle SetPropertyToField(LookupResult* lookup, + Handle name, + Handle value) { Representation representation = lookup->representation(); if (!value->FitsRepresentation(representation) || lookup->type() == CONSTANT) { - MaybeObject* maybe_failure = - lookup->holder()->GeneralizeFieldRepresentation( - lookup->GetDescriptorIndex(), - value->OptimalRepresentation(), - FORCE_FIELD); - if (maybe_failure->IsFailure()) return maybe_failure; + JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()), + lookup->GetDescriptorIndex(), + value->OptimalRepresentation(), + FORCE_FIELD); DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); int descriptor = lookup->GetDescriptorIndex(); representation = desc->GetDetails(descriptor).representation(); @@ -3833,199 +3837,189 @@ static MaybeObject* SetPropertyToField(LookupResult* lookup, HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( lookup->GetFieldIndex().field_index())); storage->set_value(value->Number()); - return *value; + return value; } lookup->holder()->FastPropertyAtPut( lookup->GetFieldIndex().field_index(), *value); - return *value; + return value; } -static MaybeObject* ConvertAndSetLocalProperty(LookupResult* lookup, - Name* name, - Object* value, - PropertyAttributes attributes) { - JSObject* object = lookup->holder(); +static Handle ConvertAndSetLocalProperty( + LookupResult* lookup, + Handle name, + Handle value, + PropertyAttributes attributes) { + Handle object(lookup->holder()); if (object->TooManyFastProperties()) { - MaybeObject* maybe_failure = object->NormalizeProperties( - CLEAR_INOBJECT_PROPERTIES, 0); - if (maybe_failure->IsFailure()) return maybe_failure; + JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); } if (!object->HasFastProperties()) { - return object->ReplaceSlowProperty(name, value, attributes); + return ReplaceSlowProperty(object, name, value, attributes); } int descriptor_index = lookup->GetDescriptorIndex(); if (lookup->GetAttributes() == attributes) { - MaybeObject* maybe_failure = object->GeneralizeFieldRepresentation( - descriptor_index, Representation::Tagged(), FORCE_FIELD); - if (maybe_failure->IsFailure()) return maybe_failure; + JSObject::GeneralizeFieldRepresentation( + object, descriptor_index, Representation::Tagged(), FORCE_FIELD); } else { - Map* map; - MaybeObject* maybe_map = object->map()->CopyGeneralizeAllRepresentations( + Handle old_map(object->map()); + Handle new_map = Map::CopyGeneralizeAllRepresentations(old_map, descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); - if (!maybe_map->To(&map)) return maybe_map; - MaybeObject* maybe_failure = object->MigrateToMap(map); - if (maybe_failure->IsFailure()) return maybe_failure; + JSObject::MigrateToMap(object, new_map); } DescriptorArray* descriptors = object->map()->instance_descriptors(); int index = descriptors->GetDetails(descriptor_index).field_index(); - object->FastPropertyAtPut(index, value); + object->FastPropertyAtPut(index, *value); return value; } -static MaybeObject* SetPropertyToFieldWithAttributes( +static Handle SetPropertyToFieldWithAttributes( LookupResult* lookup, Handle name, Handle value, PropertyAttributes attributes) { if (lookup->GetAttributes() == attributes) { - if (value->IsUninitialized()) return *value; + if (value->IsUninitialized()) return value; return SetPropertyToField(lookup, name, value); } else { - return ConvertAndSetLocalProperty(lookup, *name, *value, attributes); + return ConvertAndSetLocalProperty(lookup, name, value, attributes); } } -MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, - Name* name_raw, - Object* value_raw, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - StoreFromKeyed store_mode) { - Heap* heap = GetHeap(); - Isolate* isolate = heap->isolate(); +Handle JSObject::SetPropertyForResult(Handle object, + LookupResult* lookup, + Handle name, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode, + StoreFromKeyed store_mode) { + Isolate* isolate = object->GetIsolate(); // Make sure that the top context does not change when doing callbacks or // interceptor calls. - AssertNoContextChangeWithHandleScope ncc; + AssertNoContextChange ncc; // Optimization for 2-byte strings often used as keys in a decompression // dictionary. We internalize these short keys to avoid constantly // reallocating them. - if (name_raw->IsString() && !name_raw->IsInternalizedString() && - String::cast(name_raw)->length() <= 2) { - Object* internalized_version; - { MaybeObject* maybe_string_version = - heap->InternalizeString(String::cast(name_raw)); - if (maybe_string_version->ToObject(&internalized_version)) { - name_raw = String::cast(internalized_version); - } - } + if (name->IsString() && !name->IsInternalizedString() && + Handle::cast(name)->length() <= 2) { + name = isolate->factory()->InternalizeString(Handle::cast(name)); } // Check access rights if needed. - if (IsAccessCheckNeeded()) { - if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) { - return SetPropertyWithFailedAccessCheck( - lookup, name_raw, value_raw, true, strict_mode); + if (object->IsAccessCheckNeeded()) { + if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { + CALL_HEAP_FUNCTION( + isolate, + object->SetPropertyWithFailedAccessCheck( + lookup, *name, *value, true, strict_mode), + Object); } } - 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)->SetPropertyForResult( - lookup, name_raw, value_raw, attributes, strict_mode, store_mode); + return SetPropertyForResult(Handle::cast(proto), + lookup, name, value, attributes, strict_mode, store_mode); } - ASSERT(!lookup->IsFound() || lookup->holder() == this || + ASSERT(!lookup->IsFound() || lookup->holder() == *object || lookup->holder()->map()->is_hidden_prototype()); - // From this point on everything needs to be handlified, because - // SetPropertyViaPrototypes might call back into JavaScript. - HandleScope scope(isolate); - Handle self(this); - Handle name(name_raw); - Handle value(value_raw, isolate); - - if (!lookup->IsProperty() && !self->IsJSContextExtensionObject()) { + if (!lookup->IsProperty() && !object->IsJSContextExtensionObject()) { bool done = false; - MaybeObject* result_object = self->SetPropertyViaPrototypes( - *name, *value, attributes, strict_mode, &done); + Handle result_object = SetPropertyViaPrototypes( + object, name, value, attributes, strict_mode, &done); if (done) return result_object; } if (!lookup->IsFound()) { // Neither properties nor transitions found. - return self->AddProperty( - *name, *value, attributes, strict_mode, store_mode); + return AddProperty( + object, name, value, attributes, strict_mode, store_mode); } if (lookup->IsProperty() && lookup->IsReadOnly()) { if (strict_mode == kStrictMode) { - Handle args[] = { name, self }; - return isolate->Throw(*isolate->factory()->NewTypeError( - "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); + Handle args[] = { name, object }; + Handle error = isolate->factory()->NewTypeError( + "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); + isolate->Throw(*error); + return Handle(); } else { - return *value; + return value; } } - Handle old_value(heap->the_hole_value(), isolate); + Handle old_value = isolate->factory()->the_hole_value(); if (FLAG_harmony_observation && - map()->is_observed() && lookup->IsDataProperty()) { - old_value = Object::GetProperty(self, name); + object->map()->is_observed() && lookup->IsDataProperty()) { + old_value = Object::GetProperty(object, name); } // This is a real property that is not read-only, or it is a // transition or null descriptor and there are no setters in the prototypes. - MaybeObject* result = *value; + Handle result = value; switch (lookup->type()) { case NORMAL: - result = lookup->holder()->SetNormalizedProperty(lookup, *value); + result = SetNormalizedProperty(handle(lookup->holder()), lookup, value); break; case FIELD: result = SetPropertyToField(lookup, name, value); break; case CONSTANT: // Only replace the constant if necessary. - if (*value == lookup->GetConstant()) return *value; + if (*value == lookup->GetConstant()) return value; result = SetPropertyToField(lookup, name, value); break; case CALLBACKS: { - Object* callback_object = lookup->GetCallbackObject(); - return self->SetPropertyWithCallback( - callback_object, *name, *value, lookup->holder(), strict_mode); + Handle callback_object(lookup->GetCallbackObject(), isolate); + CALL_HEAP_FUNCTION( + isolate, + object->SetPropertyWithCallback(*callback_object, *name, *value, + lookup->holder(), strict_mode), + Object); } case INTERCEPTOR: - result = lookup->holder()->SetPropertyWithInterceptor( - *name, *value, attributes, strict_mode); + result = SetPropertyWithInterceptor(handle(lookup->holder()), name, value, + attributes, strict_mode); break; - case TRANSITION: { - result = SetPropertyUsingTransition(lookup, name, value, attributes); + case TRANSITION: + result = SetPropertyUsingTransition(handle(lookup->holder()), lookup, + name, value, attributes); break; - } case HANDLER: case NONEXISTENT: UNREACHABLE(); } - Handle hresult; - if (!result->ToHandle(&hresult, isolate)) return result; + RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle()); - if (FLAG_harmony_observation && self->map()->is_observed()) { + if (FLAG_harmony_observation && object->map()->is_observed()) { if (lookup->IsTransition()) { - EnqueueChangeRecord(self, "new", name, old_value); + EnqueueChangeRecord(object, "new", name, old_value); } else { LookupResult new_lookup(isolate); - self->LocalLookup(*name, &new_lookup, true); + object->LocalLookup(*name, &new_lookup, true); if (new_lookup.IsDataProperty()) { - Handle new_value = Object::GetProperty(self, name); + Handle new_value = Object::GetProperty(object, name); if (!new_value->SameValue(*old_value)) { - EnqueueChangeRecord(self, "updated", name, old_value); + EnqueueChangeRecord(object, "updated", name, old_value); } } } } - return *hresult; + return result; } @@ -4063,91 +4057,69 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributesTrampoline( // doesn't handle function prototypes correctly. Handle JSObject::SetLocalPropertyIgnoreAttributes( Handle object, - Handle key, + Handle name, Handle value, PropertyAttributes attributes, ValueType value_type, StoreMode mode, ExtensibilityCheck extensibility_check) { - CALL_HEAP_FUNCTION( - object->GetIsolate(), - object->SetLocalPropertyIgnoreAttributes( - *key, *value, attributes, value_type, mode, extensibility_check), - Object); -} - + Isolate* isolate = object->GetIsolate(); -MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( - Name* name_raw, - Object* value_raw, - PropertyAttributes attributes, - ValueType value_type, - StoreMode mode, - ExtensibilityCheck extensibility_check) { // Make sure that the top context does not change when doing callbacks or // interceptor calls. - AssertNoContextChangeWithHandleScope ncc; - Isolate* isolate = GetIsolate(); + AssertNoContextChange ncc; + LookupResult lookup(isolate); - LocalLookup(name_raw, &lookup, true); - if (!lookup.IsFound()) map()->LookupTransition(this, name_raw, &lookup); + object->LocalLookup(*name, &lookup, true); + if (!lookup.IsFound()) { + object->map()->LookupTransition(*object, *name, &lookup); + } + // Check access rights if needed. - if (IsAccessCheckNeeded()) { - if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) { - return SetPropertyWithFailedAccessCheck(&lookup, - name_raw, - value_raw, - false, - kNonStrictMode); + if (object->IsAccessCheckNeeded()) { + if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { + CALL_HEAP_FUNCTION( + isolate, + object->SetPropertyWithFailedAccessCheck( + &lookup, *name, *value, false, kNonStrictMode), + Object); } } - 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)->SetLocalPropertyIgnoreAttributes( - name_raw, - value_raw, - attributes, - value_type, - mode, - extensibility_check); + return SetLocalPropertyIgnoreAttributes(Handle::cast(proto), + name, value, attributes, value_type, mode, extensibility_check); } if (lookup.IsFound() && (lookup.type() == INTERCEPTOR || lookup.type() == CALLBACKS)) { - LocalLookupRealNamedProperty(name_raw, &lookup); + object->LocalLookupRealNamedProperty(*name, &lookup); } // Check for accessor in prototype chain removed here in clone. if (!lookup.IsFound()) { // Neither properties nor transitions found. - return AddProperty( - name_raw, value_raw, attributes, kNonStrictMode, + return AddProperty(object, name, value, attributes, kNonStrictMode, MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); } - // From this point on everything needs to be handlified. - HandleScope scope(isolate); - Handle self(this); - Handle name(name_raw); - Handle value(value_raw, isolate); - - Handle old_value(isolate->heap()->the_hole_value(), isolate); + Handle old_value = isolate->factory()->the_hole_value(); PropertyAttributes old_attributes = ABSENT; - bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); + bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); if (is_observed && lookup.IsProperty()) { if (lookup.IsDataProperty()) old_value = - Object::GetProperty(self, name); + Object::GetProperty(object, name); old_attributes = lookup.GetAttributes(); } // Check of IsReadOnly removed from here in clone. - MaybeObject* result = *value; + Handle result = value; switch (lookup.type()) { case NORMAL: - result = self->ReplaceSlowProperty(*name, *value, attributes); + result = ReplaceSlowProperty(object, name, value, attributes); break; case FIELD: result = SetPropertyToFieldWithAttributes( @@ -4162,10 +4134,11 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( } break; case CALLBACKS: - result = ConvertAndSetLocalProperty(&lookup, *name, *value, attributes); + result = ConvertAndSetLocalProperty(&lookup, name, value, attributes); break; case TRANSITION: - result = SetPropertyUsingTransition(&lookup, name, value, attributes); + result = SetPropertyUsingTransition(handle(lookup.holder()), &lookup, + name, value, attributes); break; case NONEXISTENT: case HANDLER: @@ -4173,32 +4146,31 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( UNREACHABLE(); } - Handle hresult; - if (!result->ToHandle(&hresult, isolate)) return result; + if (result.is_null()) return result; if (is_observed) { if (lookup.IsTransition()) { - EnqueueChangeRecord(self, "new", name, old_value); + EnqueueChangeRecord(object, "new", name, old_value); } else if (old_value->IsTheHole()) { - EnqueueChangeRecord(self, "reconfigured", name, old_value); + EnqueueChangeRecord(object, "reconfigured", name, old_value); } else { LookupResult new_lookup(isolate); - self->LocalLookup(*name, &new_lookup, true); + object->LocalLookup(*name, &new_lookup, true); bool value_changed = false; if (new_lookup.IsDataProperty()) { - Handle new_value = Object::GetProperty(self, name); + Handle new_value = Object::GetProperty(object, name); value_changed = !old_value->SameValue(*new_value); } if (new_lookup.GetAttributes() != old_attributes) { if (!value_changed) old_value = isolate->factory()->the_hole_value(); - EnqueueChangeRecord(self, "reconfigured", name, old_value); + EnqueueChangeRecord(object, "reconfigured", name, old_value); } else if (value_changed) { - EnqueueChangeRecord(self, "updated", name, old_value); + EnqueueChangeRecord(object, "updated", name, old_value); } } } - return *hresult; + return result; } @@ -6690,6 +6662,15 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, } +Handle Map::CopyInstallDescriptors(Handle map, + int new_descriptor, + Handle descriptors) { + CALL_HEAP_FUNCTION(map->GetIsolate(), + map->CopyInstallDescriptors(new_descriptor, *descriptors), + Map); +} + + // Since this method is used to rewrite an existing transition tree, it can // always insert transitions without checking. MaybeObject* Map::CopyInstallDescriptors(int new_descriptor, @@ -7802,6 +7783,20 @@ void DescriptorArray::CopyFrom(int dst_index, } +Handle DescriptorArray::Merge(Handle desc, + int verbatim, + int valid, + int new_size, + int modify_index, + StoreMode store_mode, + Handle other) { + CALL_HEAP_FUNCTION(desc->GetIsolate(), + desc->Merge(verbatim, valid, new_size, modify_index, + store_mode, *other), + DescriptorArray); +} + + // Generalize the |other| descriptor array by merging it into the (at least // partly) updated |this| descriptor array. // The method merges two descriptor array in three parts. Both descriptor arrays @@ -14524,17 +14519,6 @@ PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { } -// TODO(mstarzinger): Temporary wrapper until handlified. -static Handle NameDictionaryAdd(Handle dict, - Handle name, - Handle value, - PropertyDetails details) { - CALL_HEAP_FUNCTION(dict->GetIsolate(), - dict->Add(*name, *value, details), - NameDictionary); -} - - Handle GlobalObject::EnsurePropertyCell( Handle global, Handle name) { @@ -16113,6 +16097,14 @@ Type* PropertyCell::UpdateType(Handle cell, } +void PropertyCell::SetValueInferType(Handle cell, + Handle value, + WriteBarrierMode mode) { + CALL_HEAP_FUNCTION_VOID(cell->GetIsolate(), + cell->SetValueInferType(*value, mode)); +} + + MaybeObject* PropertyCell::SetValueInferType(Object* value, WriteBarrierMode ignored) { set_value(value, ignored); diff --git a/src/objects.h b/src/objects.h index e5c1a22..dffc46d 100644 --- a/src/objects.h +++ b/src/objects.h @@ -1950,42 +1950,24 @@ class JSReceiver: public HeapObject { // Casting. static inline JSReceiver* cast(Object* obj); + // Implementation of [[Put]], see ECMA-262 5th edition, section 8.12.5. static Handle SetProperty(Handle object, Handle key, Handle value, PropertyAttributes attributes, - StrictModeFlag strict_mode); + StrictModeFlag strict_mode, + StoreFromKeyed store_mode = + MAY_BE_STORE_FROM_KEYED); static Handle SetElement(Handle object, uint32_t index, Handle value, PropertyAttributes attributes, StrictModeFlag strict_mode); - MUST_USE_RESULT static MaybeObject* SetPropertyOrFail( - Handle object, - Handle key, - Handle value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - StoreFromKeyed store_from_keyed = MAY_BE_STORE_FROM_KEYED); - - // Can cause GC. - MUST_USE_RESULT MaybeObject* SetProperty( - Name* key, - Object* value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - StoreFromKeyed store_from_keyed = MAY_BE_STORE_FROM_KEYED); - MUST_USE_RESULT MaybeObject* SetProperty( - LookupResult* result, - Name* key, - Object* value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - StoreFromKeyed store_from_keyed = MAY_BE_STORE_FROM_KEYED); MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSReceiver* setter, Object* value); + // Implementation of [[Delete]], see ECMA-262 5th edition, section 8.12.7. static Handle DeleteProperty(Handle object, Handle name, DeleteMode mode = NORMAL_DELETION); @@ -2042,6 +2024,14 @@ class JSReceiver: public HeapObject { Name* name, bool continue_search); + static Handle SetProperty(Handle receiver, + LookupResult* result, + Handle key, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode, + StoreFromKeyed store_from_keyed); + DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver); }; @@ -2135,13 +2125,6 @@ class JSObject: public JSReceiver { Object* structure, Name* name); - // Can cause GC. - MUST_USE_RESULT MaybeObject* SetPropertyForResult(LookupResult* result, - Name* key, - Object* value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - StoreFromKeyed store_mode); MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck( LookupResult* result, Name* name, @@ -2154,17 +2137,21 @@ class JSObject: public JSReceiver { Object* value, JSObject* holder, StrictModeFlag strict_mode); - MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor( - Name* name, - Object* value, + static Handle SetPropertyWithInterceptor( + Handle object, + Handle name, + Handle value, PropertyAttributes attributes, StrictModeFlag strict_mode); - MUST_USE_RESULT MaybeObject* SetPropertyPostInterceptor( - Name* name, - Object* value, + + static Handle SetPropertyForResult( + Handle object, + LookupResult* result, + Handle name, + Handle value, PropertyAttributes attributes, StrictModeFlag strict_mode, - StoreMode mode = ALLOW_AS_CONSTANT); + StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED); static Handle SetLocalPropertyIgnoreAttributes( Handle object, @@ -2191,7 +2178,6 @@ class JSObject: public JSReceiver { inline MUST_USE_RESULT MaybeObject* AllocateStorageForMap(Map* map); static void MigrateInstance(Handle instance); - inline MUST_USE_RESULT MaybeObject* MigrateInstance(); static Handle TryMigrateInstance(Handle instance); inline MUST_USE_RESULT MaybeObject* TryMigrateInstance(); @@ -2483,32 +2469,6 @@ class JSObject: public JSReceiver { // Returns the number of enumerable elements. int GetEnumElementKeys(FixedArray* storage); - // Add a property to a fast-case object using a map transition to - // new_map. - MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap( - Map* new_map, - Name* name, - Object* value, - int field_index, - Representation representation); - - // Add a constant function property to a fast-case object. - // This leaves a CONSTANT_TRANSITION in the old map, and - // if it is called on a second object with this map, a - // normal property is added instead, with a map transition. - // This avoids the creation of many maps with the same constant - // function, all orphaned. - MUST_USE_RESULT MaybeObject* AddConstantProperty( - Name* name, - Object* constant, - PropertyAttributes attributes, - TransitionFlag flag); - - MUST_USE_RESULT MaybeObject* ReplaceSlowProperty( - Name* name, - Object* value, - PropertyAttributes attributes); - // Returns a new map with all transitions dropped from the object's current // map and the ElementsKind set. static Handle GetElementsTransitionMap(Handle object, @@ -2525,37 +2485,12 @@ class JSObject: public JSReceiver { MUST_USE_RESULT MaybeObject* TransitionElementsKind(ElementsKind to_kind); MUST_USE_RESULT MaybeObject* UpdateAllocationSite(ElementsKind to_kind); + static void MigrateToMap(Handle object, Handle new_map); MUST_USE_RESULT MaybeObject* MigrateToMap(Map* new_map); - MUST_USE_RESULT MaybeObject* GeneralizeFieldRepresentation( - int modify_index, - Representation new_representation, - StoreMode store_mode); - - // Add a property to a fast-case object. - MUST_USE_RESULT MaybeObject* AddFastProperty( - Name* name, - Object* value, - PropertyAttributes attributes, - StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED, - ValueType value_type = OPTIMAL_REPRESENTATION, - TransitionFlag flag = INSERT_TRANSITION); - - // Add a property to a slow-case object. - MUST_USE_RESULT MaybeObject* AddSlowProperty(Name* name, - Object* value, - PropertyAttributes attributes); - - // Add a property to an object. May cause GC. - MUST_USE_RESULT MaybeObject* AddProperty( - Name* name, - Object* value, - PropertyAttributes attributes, - StrictModeFlag strict_mode, - StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED, - ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK, - ValueType value_type = OPTIMAL_REPRESENTATION, - StoreMode mode = ALLOW_AS_CONSTANT, - TransitionFlag flag = INSERT_TRANSITION); + static void GeneralizeFieldRepresentation(Handle object, + int modify_index, + Representation new_representation, + StoreMode store_mode); // Convert the object to use the canonical dictionary // representation. If the object is expected to have additional properties @@ -2735,15 +2670,6 @@ class JSObject: public JSReceiver { friend class DictionaryElementsAccessor; friend class JSReceiver; - // TODO(mstarzinger): Soon to be handlified. - MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes( - Name* key, - Object* value, - PropertyAttributes attributes, - ValueType value_type = OPTIMAL_REPRESENTATION, - StoreMode mode = ALLOW_AS_CONSTANT, - ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK); - MUST_USE_RESULT MaybeObject* GetElementWithCallback(Object* receiver, Object* structure, uint32_t index, @@ -2780,13 +2706,81 @@ class JSObject: public JSReceiver { // 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 // read-only, reject and set '*done' to true. Otherwise, set '*done' to - // false. Can cause GC and can return a failure result with '*done==true'. - MUST_USE_RESULT MaybeObject* SetPropertyViaPrototypes( - Name* name, - Object* value, + // false. Can throw and return an empty handle with '*done==true'. + static Handle SetPropertyViaPrototypes( + Handle object, + Handle name, + Handle value, PropertyAttributes attributes, StrictModeFlag strict_mode, bool* done); + static Handle SetPropertyPostInterceptor( + Handle object, + Handle name, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode); + static Handle SetPropertyUsingTransition( + Handle object, + LookupResult* lookup, + Handle name, + Handle value, + PropertyAttributes attributes); + + // Add a property to an object. + static Handle AddProperty( + Handle object, + Handle name, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode, + StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED, + ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK, + ValueType value_type = OPTIMAL_REPRESENTATION, + StoreMode mode = ALLOW_AS_CONSTANT, + TransitionFlag flag = INSERT_TRANSITION); + + // Add a constant function property to a fast-case object. + // This leaves a CONSTANT_TRANSITION in the old map, and + // if it is called on a second object with this map, a + // normal property is added instead, with a map transition. + // This avoids the creation of many maps with the same constant + // function, all orphaned. + static void AddConstantProperty(Handle object, + Handle name, + Handle constant, + PropertyAttributes attributes, + TransitionFlag flag); + + // Add a property to a fast-case object. + static void AddFastProperty(Handle object, + Handle name, + Handle value, + PropertyAttributes attributes, + StoreFromKeyed store_mode, + ValueType value_type, + TransitionFlag flag); + + // Add a property to a fast-case object using a map transition to + // new_map. + static Handle AddFastPropertyUsingMap(Handle object, + Handle new_map, + Handle name, + Handle value, + int field_index, + Representation representation); + MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap( + Map* new_map, + Name* name, + Object* value, + int field_index, + Representation representation); + + // Add a property to a slow-case object. + static void AddSlowProperty(Handle object, + Handle name, + Handle value, + PropertyAttributes attributes); static Handle DeleteProperty(Handle object, Handle name, @@ -3176,6 +3170,13 @@ class DescriptorArray: public FixedArray { DescriptorArray* src, int src_index, const WhitenessWitness&); + static Handle Merge(Handle desc, + int verbatim, + int valid, + int new_size, + int modify_index, + StoreMode store_mode, + Handle other); MUST_USE_RESULT MaybeObject* Merge(int verbatim, int valid, int new_size, @@ -5618,11 +5619,8 @@ class Map: public HeapObject { int modify_index, Representation new_representation, StoreMode store_mode); - MUST_USE_RESULT MaybeObject* GeneralizeRepresentation( - int modify_index, - Representation representation, - StoreMode store_mode); - MUST_USE_RESULT MaybeObject* CopyGeneralizeAllRepresentations( + static Handle CopyGeneralizeAllRepresentations( + Handle map, int modify_index, StoreMode store_mode, PropertyAttributes attributes, @@ -5802,6 +5800,10 @@ class Map: public HeapObject { TransitionFlag flag, Name* name = NULL, SimpleTransitionFlag simple_flag = FULL_TRANSITION); + static Handle CopyInstallDescriptors( + Handle map, + int new_descriptor, + Handle descriptors); MUST_USE_RESULT MaybeObject* CopyInstallDescriptors( int new_descriptor, DescriptorArray* descriptors); @@ -9020,6 +9022,9 @@ class PropertyCell: public Cell { // of the cell's current type and the value's type. If the change causes // a change of the type of the cell's contents, code dependent on the cell // will be deoptimized. + static void SetValueInferType(Handle cell, + Handle value, + WriteBarrierMode mode = UPDATE_WRITE_BARRIER); MUST_USE_RESULT MaybeObject* SetValueInferType( Object* value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); @@ -9082,13 +9087,6 @@ class JSProxy: public JSReceiver { Object* receiver, uint32_t index); - MUST_USE_RESULT MaybeObject* SetPropertyWithHandler( - JSReceiver* receiver, - Name* name, - Object* value, - PropertyAttributes attributes, - StrictModeFlag strict_mode); - // If the handler defines an accessor property with a setter, invoke it. // If it defines an accessor property without a setter, or a data property // that is read-only, throw. In all these cases set '*done' to true, @@ -9144,6 +9142,12 @@ class JSProxy: public JSReceiver { private: friend class JSReceiver; + static Handle SetPropertyWithHandler(Handle proxy, + Handle receiver, + Handle name, + Handle value, + PropertyAttributes attributes, + StrictModeFlag strict_mode); static Handle SetElementWithHandler(Handle proxy, Handle receiver, uint32_t index, diff --git a/src/runtime.cc b/src/runtime.cc index a698445..238157f 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -2201,7 +2201,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - SealHandleScope shs(isolate); + HandleScope scope(isolate); // args[0] == name // args[1] == language_mode // args[2] == value (optional) @@ -2212,7 +2212,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { bool assign = args.length() == 3; CONVERT_ARG_HANDLE_CHECKED(String, name, 0); - GlobalObject* global = isolate->context()->global_object(); RUNTIME_ASSERT(args[1]->IsSmi()); CONVERT_LANGUAGE_MODE_ARG(language_mode, 1); StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE) @@ -2229,28 +2228,33 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { // to assign to the property. // Note that objects can have hidden prototypes, so we need to traverse // the whole chain of hidden prototypes to do a 'local' lookup. - Object* object = global; LookupResult lookup(isolate); - JSObject::cast(object)->LocalLookup(*name, &lookup, true); + isolate->context()->global_object()->LocalLookup(*name, &lookup, true); if (lookup.IsInterceptor()) { - HandleScope handle_scope(isolate); PropertyAttributes intercepted = lookup.holder()->GetPropertyAttribute(*name); if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) { // Found an interceptor that's not read only. if (assign) { - return lookup.holder()->SetProperty( - &lookup, *name, args[2], attributes, strict_mode_flag); + CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); + Handle result = JSObject::SetPropertyForResult( + handle(lookup.holder()), &lookup, name, value, attributes, + strict_mode_flag); + RETURN_IF_EMPTY_HANDLE(isolate, result); + return *result; } else { return isolate->heap()->undefined_value(); } } } - // Reload global in case the loop above performed a GC. - global = isolate->context()->global_object(); if (assign) { - return global->SetProperty(*name, args[2], attributes, strict_mode_flag); + CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); + Handle global(isolate->context()->global_object()); + Handle result = JSReceiver::SetProperty( + global, name, value, attributes, strict_mode_flag); + RETURN_IF_EMPTY_HANDLE(isolate, result); + return *result; } return isolate->heap()->undefined_value(); } @@ -5133,11 +5137,14 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, if (object->IsJSProxy()) { bool has_pending_exception = false; - Handle name = key->IsSymbol() + Handle name_object = key->IsSymbol() ? key : Execution::ToString(isolate, key, &has_pending_exception); if (has_pending_exception) return Failure::Exception(); - return JSProxy::cast(*object)->SetProperty( - Name::cast(*name), *value, attr, strict_mode); + Handle name = Handle::cast(name_object); + Handle result = JSReceiver::SetProperty( + Handle::cast(object), name, value, attr, strict_mode); + RETURN_IF_EMPTY_HANDLE(isolate, result); + return *result; } // If the object isn't a JavaScript object, we ignore the store. @@ -5177,7 +5184,6 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, } if (key->IsName()) { - MaybeObject* result; Handle name = Handle::cast(key); if (name->AsArrayIndex(&index)) { if (js_object->HasExternalArrayElements()) { @@ -5189,13 +5195,15 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, value = number; } } - result = js_object->SetElement( + MaybeObject* result = js_object->SetElement( index, *value, attr, strict_mode, true, set_mode); + if (result->IsFailure()) return result; } else { if (name->IsString()) Handle::cast(name)->TryFlatten(); - result = js_object->SetProperty(*name, *value, attr, strict_mode); + Handle result = + JSReceiver::SetProperty(js_object, name, value, attr, strict_mode); + RETURN_IF_EMPTY_HANDLE(isolate, result); } - if (result->IsFailure()) return result; return *value; } @@ -5210,7 +5218,10 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, return js_object->SetElement( index, *value, attr, strict_mode, true, set_mode); } else { - return js_object->SetProperty(*name, *value, attr, strict_mode); + Handle result = + JSReceiver::SetProperty(js_object, name, value, attr, strict_mode); + RETURN_IF_EMPTY_HANDLE(isolate, result); + return *result; } } diff --git a/src/stub-cache.cc b/src/stub-cache.cc index 338ed2a..f136083 100644 --- a/src/stub-cache.cc +++ b/src/stub-cache.cc @@ -1395,17 +1395,19 @@ RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) { RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) { + HandleScope scope(isolate); ASSERT(args.length() == 4); - JSObject* recv = JSObject::cast(args[0]); - Name* name = Name::cast(args[1]); - Object* value = args[2]; + Handle recv(JSObject::cast(args[0])); + Handle name(Name::cast(args[1])); + Handle value(args[2], isolate); ASSERT(args.smi_at(3) == kStrictMode || args.smi_at(3) == kNonStrictMode); StrictModeFlag strict_mode = static_cast(args.smi_at(3)); ASSERT(recv->HasNamedInterceptor()); PropertyAttributes attr = NONE; - MaybeObject* result = recv->SetPropertyWithInterceptor( - name, value, attr, strict_mode); - return result; + Handle result = JSObject::SetPropertyWithInterceptor( + recv, name, value, attr, strict_mode); + RETURN_IF_EMPTY_HANDLE(isolate, result); + return *result; } diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 7375c5a..ff8c00f 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -14649,11 +14649,12 @@ class RegExpStringModificationTest { // Inject the input as a global variable. i::Handle input_name = factory->NewStringFromAscii(i::Vector("input", 5)); - i::Isolate::Current()->native_context()->global_object()->SetProperty( - *input_name, - *input_, + i::JSReceiver::SetProperty( + i::handle(i::Isolate::Current()->native_context()->global_object()), + input_name, + input_, NONE, - i::kNonStrictMode)->ToObjectChecked(); + i::kNonStrictMode); MorphThread morph_thread(this); morph_thread.Start(); diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index 9e4e907..be51193 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -262,6 +262,8 @@ TEST(GarbageCollection) { Handle prop_name = factory->InternalizeUtf8String("theSlot"); Handle prop_namex = factory->InternalizeUtf8String("theSlotx"); Handle obj_name = factory->InternalizeUtf8String("theObject"); + Handle twenty_three(Smi::FromInt(23), isolate); + Handle twenty_four(Smi::FromInt(24), isolate); { HandleScope inner_scope(isolate); @@ -271,14 +273,12 @@ TEST(GarbageCollection) { Handle initial_map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); function->set_initial_map(*initial_map); - Isolate::Current()->context()->global_object()->SetProperty( - *name, *function, NONE, kNonStrictMode)->ToObjectChecked(); + Handle global(Isolate::Current()->context()->global_object()); + JSReceiver::SetProperty(global, name, function, NONE, kNonStrictMode); // Allocate an object. Unrooted after leaving the scope. Handle obj = factory->NewJSObject(function); - obj->SetProperty( - *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); - obj->SetProperty( - *prop_namex, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked(); + JSReceiver::SetProperty(obj, prop_name, twenty_three, NONE, kNonStrictMode); + JSReceiver::SetProperty(obj, prop_namex, twenty_four, NONE, kNonStrictMode); CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex)); @@ -299,10 +299,9 @@ TEST(GarbageCollection) { HandleScope inner_scope(isolate); // Allocate another object, make it reachable from global. Handle obj = factory->NewJSObject(function); - Isolate::Current()->context()->global_object()->SetProperty( - *obj_name, *obj, NONE, kNonStrictMode)->ToObjectChecked(); - obj->SetProperty( - *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); + Handle global(Isolate::Current()->context()->global_object()); + JSReceiver::SetProperty(global, obj_name, obj, NONE, kNonStrictMode); + JSReceiver::SetProperty(obj, prop_name, twenty_three, NONE, kNonStrictMode); } // After gc, it should survive. @@ -628,14 +627,16 @@ TEST(FunctionAllocation) { factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); function->set_initial_map(*initial_map); + Handle twenty_three(Smi::FromInt(23), isolate); + Handle twenty_four(Smi::FromInt(24), isolate); + Handle prop_name = factory->InternalizeUtf8String("theSlot"); Handle obj = factory->NewJSObject(function); - obj->SetProperty( - *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); + JSReceiver::SetProperty(obj, prop_name, twenty_three, NONE, kNonStrictMode); CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); // Check that we can add properties to function objects. - function->SetProperty( - *prop_name, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked(); + JSReceiver::SetProperty(function, prop_name, twenty_four, NONE, + kNonStrictMode); CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name)); } @@ -655,12 +656,14 @@ TEST(ObjectProperties) { Handle first = factory->InternalizeUtf8String("first"); Handle second = factory->InternalizeUtf8String("second"); + Handle one(Smi::FromInt(1), isolate); + Handle two(Smi::FromInt(2), isolate); + // check for empty CHECK(!obj->HasLocalProperty(*first)); // add first - obj->SetProperty( - *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); + JSReceiver::SetProperty(obj, first, one, NONE, kNonStrictMode); CHECK(obj->HasLocalProperty(*first)); // delete first @@ -668,10 +671,8 @@ TEST(ObjectProperties) { CHECK(!obj->HasLocalProperty(*first)); // add first and then second - obj->SetProperty( - *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); - obj->SetProperty( - *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked(); + JSReceiver::SetProperty(obj, first, one, NONE, kNonStrictMode); + JSReceiver::SetProperty(obj, second, two, NONE, kNonStrictMode); CHECK(obj->HasLocalProperty(*first)); CHECK(obj->HasLocalProperty(*second)); @@ -683,10 +684,8 @@ TEST(ObjectProperties) { CHECK(!obj->HasLocalProperty(*second)); // add first and then second - obj->SetProperty( - *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); - obj->SetProperty( - *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked(); + JSReceiver::SetProperty(obj, first, one, NONE, kNonStrictMode); + JSReceiver::SetProperty(obj, second, two, NONE, kNonStrictMode); CHECK(obj->HasLocalProperty(*first)); CHECK(obj->HasLocalProperty(*second)); @@ -700,16 +699,14 @@ TEST(ObjectProperties) { // check string and internalized string match const char* string1 = "fisk"; Handle s1 = factory->NewStringFromAscii(CStrVector(string1)); - obj->SetProperty( - *s1, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); + JSReceiver::SetProperty(obj, s1, one, NONE, kNonStrictMode); Handle s1_string = factory->InternalizeUtf8String(string1); CHECK(obj->HasLocalProperty(*s1_string)); // check internalized string and string match const char* string2 = "fugl"; Handle s2_string = factory->InternalizeUtf8String(string2); - obj->SetProperty( - *s2_string, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); + JSReceiver::SetProperty(obj, s2_string, one, NONE, kNonStrictMode); Handle s2 = factory->NewStringFromAscii(CStrVector(string2)); CHECK(obj->HasLocalProperty(*s2)); } @@ -732,8 +729,8 @@ TEST(JSObjectMaps) { Handle obj = factory->NewJSObject(function); // Set a propery - obj->SetProperty( - *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); + Handle twenty_three(Smi::FromInt(23), isolate); + JSReceiver::SetProperty(obj, prop_name, twenty_three, NONE, kNonStrictMode); CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); // Check the map has changed @@ -805,10 +802,11 @@ TEST(JSObjectCopy) { Handle first = factory->InternalizeUtf8String("first"); Handle second = factory->InternalizeUtf8String("second"); - obj->SetProperty( - *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); - obj->SetProperty( - *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked(); + Handle one(Smi::FromInt(1), isolate); + Handle two(Smi::FromInt(2), isolate); + + 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(); @@ -824,10 +822,8 @@ TEST(JSObjectCopy) { CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second)); // Flip the values. - clone->SetProperty( - *first, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked(); - clone->SetProperty( - *second, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); + 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(); @@ -3009,9 +3005,10 @@ TEST(Regression144230) { // visited later, causing the CallIC to be cleared. Handle name = isolate->factory()->InternalizeUtf8String("call"); Handle global(isolate->context()->global_object()); + Handle zero(Smi::FromInt(0), isolate); MaybeObject* maybe_call = global->GetProperty(*name); JSFunction* call = JSFunction::cast(maybe_call->ToObjectChecked()); - USE(global->SetProperty(*name, Smi::FromInt(0), NONE, kNonStrictMode)); + JSReceiver::SetProperty(global, name, zero, NONE, kNonStrictMode); isolate->compilation_cache()->Clear(); call->shared()->set_ic_age(heap->global_ic_age() + 1); Handle call_code(call->code(), isolate); @@ -3022,7 +3019,7 @@ TEST(Regression144230) { // Either heap verification caught the problem already or we go kaboom once // the CallIC is executed the next time. - USE(global->SetProperty(*name, *call_function, NONE, kNonStrictMode)); + JSReceiver::SetProperty(global, name, call_function, NONE, kNonStrictMode); CompileRun("call();"); } diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc index 33d9230..cd38392 100644 --- a/test/cctest/test-mark-compact.cc +++ b/test/cctest/test-mark-compact.cc @@ -153,6 +153,7 @@ TEST(MarkCompactCollector) { Heap* heap = isolate->heap(); v8::HandleScope sc(CcTest::isolate()); + Handle global(isolate->context()->global_object()); // call mark-compact when heap is empty heap->CollectGarbage(OLD_POINTER_SPACE, "trigger 1"); @@ -191,8 +192,8 @@ TEST(MarkCompactCollector) { Map::cast(heap->AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize)->ToObjectChecked()); function->set_initial_map(initial_map); - isolate->context()->global_object()->SetProperty( - func_name, function, NONE, kNonStrictMode)->ToObjectChecked(); + JSReceiver::SetProperty( + global, handle(func_name), handle(function), NONE, kNonStrictMode); JSObject* obj = JSObject::cast( heap->AllocateJSObject(function)->ToObjectChecked()); @@ -209,14 +210,13 @@ TEST(MarkCompactCollector) { obj = JSObject::cast(heap->AllocateJSObject(function)->ToObjectChecked()); String* obj_name = String::cast(heap->InternalizeUtf8String("theObject")->ToObjectChecked()); - isolate->context()->global_object()->SetProperty( - obj_name, obj, NONE, kNonStrictMode)->ToObjectChecked(); + JSReceiver::SetProperty( + global, handle(obj_name), handle(obj), NONE, kNonStrictMode); String* prop_name = String::cast(heap->InternalizeUtf8String("theSlot")->ToObjectChecked()); - obj->SetProperty(prop_name, - Smi::FromInt(23), - NONE, - kNonStrictMode)->ToObjectChecked(); + Handle twenty_three(Smi::FromInt(23), isolate); + JSReceiver::SetProperty( + handle(obj), handle(prop_name), twenty_three, NONE, kNonStrictMode); heap->CollectGarbage(OLD_POINTER_SPACE, "trigger 5");