| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index bddc5d7221c8af79d32180bea6012f2fb9baabfd..bb1ff053203b9d4b48e0f0990030187c04281cc6 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -455,18 +455,15 @@ Handle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy,
|
| StrictModeFlag strict_mode) {
|
| Isolate* isolate = proxy->GetIsolate();
|
| Handle<String> 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);
|
| }
|
|
|
|
|
| -bool JSProxy::HasElementWithHandler(uint32_t index) {
|
| - String* name;
|
| - MaybeObject* maybe = GetHeap()->Uint32ToString(index);
|
| - if (!maybe->To<String>(&name)) return maybe;
|
| - return HasPropertyWithHandler(name);
|
| +bool JSProxy::HasElementWithHandler(Handle<JSProxy> proxy, uint32_t index) {
|
| + Isolate* isolate = proxy->GetIsolate();
|
| + Handle<String> name = isolate->factory()->Uint32ToString(index);
|
| + return HasPropertyWithHandler(proxy, name);
|
| }
|
|
|
|
|
| @@ -643,67 +640,56 @@ Object* JSObject::GetNormalizedProperty(LookupResult* result) {
|
| }
|
|
|
|
|
| -Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object,
|
| - LookupResult* result,
|
| - Handle<Object> value) {
|
| - CALL_HEAP_FUNCTION(object->GetIsolate(),
|
| - object->SetNormalizedProperty(result, *value),
|
| - Object);
|
| -}
|
| -
|
| -
|
| -MaybeObject* JSObject::SetNormalizedProperty(LookupResult* result,
|
| - Object* value) {
|
| - ASSERT(!HasFastProperties());
|
| - if (IsGlobalObject()) {
|
| - PropertyCell* cell = PropertyCell::cast(
|
| - property_dictionary()->ValueAt(result->GetDictionaryEntry()));
|
| - MaybeObject* maybe_type = cell->SetValueInferType(value);
|
| - if (maybe_type->IsFailure()) return maybe_type;
|
| +void JSObject::SetNormalizedProperty(Handle<JSObject> object,
|
| + LookupResult* result,
|
| + Handle<Object> value) {
|
| + ASSERT(!object->HasFastProperties());
|
| + NameDictionary* property_dictionary = object->property_dictionary();
|
| + if (object->IsGlobalObject()) {
|
| + Handle<PropertyCell> cell(PropertyCell::cast(
|
| + property_dictionary->ValueAt(result->GetDictionaryEntry())));
|
| + PropertyCell::SetValueInferType(cell, value);
|
| } else {
|
| - property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
|
| + property_dictionary->ValueAtPut(result->GetDictionaryEntry(), *value);
|
| }
|
| - return value;
|
| }
|
|
|
|
|
| -Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object,
|
| - Handle<Name> key,
|
| - Handle<Object> value,
|
| - PropertyDetails details) {
|
| - CALL_HEAP_FUNCTION(object->GetIsolate(),
|
| - object->SetNormalizedProperty(*key, *value, details),
|
| - Object);
|
| +// TODO(mstarzinger): Temporary wrapper until handlified.
|
| +static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| + PropertyDetails details) {
|
| + CALL_HEAP_FUNCTION(dict->GetIsolate(),
|
| + dict->Add(*name, *value, details),
|
| + NameDictionary);
|
| }
|
|
|
|
|
| -MaybeObject* JSObject::SetNormalizedProperty(Name* name,
|
| - Object* value,
|
| - PropertyDetails details) {
|
| - ASSERT(!HasFastProperties());
|
| - int entry = property_dictionary()->FindEntry(name);
|
| +void JSObject::SetNormalizedProperty(Handle<JSObject> object,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| + PropertyDetails details) {
|
| + ASSERT(!object->HasFastProperties());
|
| + Handle<NameDictionary> property_dictionary(object->property_dictionary());
|
| + int entry = property_dictionary->FindEntry(*name);
|
| if (entry == NameDictionary::kNotFound) {
|
| - Object* store_value = value;
|
| - if (IsGlobalObject()) {
|
| - Heap* heap = name->GetHeap();
|
| - MaybeObject* maybe_store_value = heap->AllocatePropertyCell(value);
|
| - if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
|
| - }
|
| - Object* dict;
|
| - { MaybeObject* maybe_dict =
|
| - property_dictionary()->Add(name, store_value, details);
|
| - if (!maybe_dict->ToObject(&dict)) return maybe_dict;
|
| + Handle<Object> store_value = value;
|
| + if (object->IsGlobalObject()) {
|
| + store_value = object->GetIsolate()->factory()->NewPropertyCell(value);
|
| }
|
| - set_properties(NameDictionary::cast(dict));
|
| - return value;
|
| + property_dictionary =
|
| + NameDictionaryAdd(property_dictionary, name, store_value, details);
|
| + object->set_properties(*property_dictionary);
|
| + return;
|
| }
|
|
|
| - PropertyDetails original_details = property_dictionary()->DetailsAt(entry);
|
| + PropertyDetails original_details = property_dictionary->DetailsAt(entry);
|
| int enumeration_index;
|
| // Preserve the enumeration index unless the property was deleted.
|
| if (original_details.IsDeleted()) {
|
| - enumeration_index = property_dictionary()->NextEnumerationIndex();
|
| - property_dictionary()->SetNextEnumerationIndex(enumeration_index + 1);
|
| + enumeration_index = property_dictionary->NextEnumerationIndex();
|
| + property_dictionary->SetNextEnumerationIndex(enumeration_index + 1);
|
| } else {
|
| enumeration_index = original_details.dictionary_index();
|
| ASSERT(enumeration_index > 0);
|
| @@ -712,17 +698,15 @@ MaybeObject* JSObject::SetNormalizedProperty(Name* name,
|
| details = PropertyDetails(
|
| details.attributes(), details.type(), enumeration_index);
|
|
|
| - if (IsGlobalObject()) {
|
| - PropertyCell* cell =
|
| - PropertyCell::cast(property_dictionary()->ValueAt(entry));
|
| - MaybeObject* maybe_type = cell->SetValueInferType(value);
|
| - if (maybe_type->IsFailure()) return maybe_type;
|
| + if (object->IsGlobalObject()) {
|
| + Handle<PropertyCell> cell(
|
| + PropertyCell::cast(property_dictionary->ValueAt(entry)));
|
| + PropertyCell::SetValueInferType(cell, value);
|
| // Please note we have to update the property details.
|
| - property_dictionary()->DetailsAtPut(entry, details);
|
| + property_dictionary->DetailsAtPut(entry, details);
|
| } else {
|
| - property_dictionary()->SetEntry(entry, name, value, details);
|
| + property_dictionary->SetEntry(entry, *name, *value, details);
|
| }
|
| - return value;
|
| }
|
|
|
|
|
| @@ -733,12 +717,6 @@ Handle<NameDictionary> NameDictionaryShrink(Handle<NameDictionary> dict,
|
| }
|
|
|
|
|
| -static void CellSetValueInferType(Handle<PropertyCell> cell,
|
| - Handle<Object> value) {
|
| - CALL_HEAP_FUNCTION_VOID(cell->GetIsolate(), cell->SetValueInferType(*value));
|
| -}
|
| -
|
| -
|
| Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
|
| Handle<Name> name,
|
| DeleteMode mode) {
|
| @@ -761,7 +739,8 @@ Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
|
| object->set_map(*new_map);
|
| }
|
| Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
|
| - CellSetValueInferType(cell, isolate->factory()->the_hole_value());
|
| + Handle<Object> value = isolate->factory()->the_hole_value();
|
| + PropertyCell::SetValueInferType(cell, value);
|
| dictionary->DetailsAtPut(entry, details.AsDeleted());
|
| } else {
|
| Handle<Object> deleted(dictionary->DeleteProperty(entry, mode), isolate);
|
| @@ -1871,211 +1850,240 @@ String* JSReceiver::constructor_name() {
|
| }
|
|
|
|
|
| -MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
|
| - Name* name,
|
| - Object* value,
|
| - int field_index,
|
| - Representation representation) {
|
| +// TODO(mstarzinger): Temporary wrapper until handlified.
|
| +static Handle<Object> NewStorageFor(Isolate* isolate,
|
| + Handle<Object> object,
|
| + Representation representation) {
|
| + Heap* heap = isolate->heap();
|
| + CALL_HEAP_FUNCTION(isolate,
|
| + object->AllocateNewStorageFor(heap, representation),
|
| + Object);
|
| +}
|
| +
|
| +
|
| +void JSObject::AddFastPropertyUsingMap(Handle<JSObject> object,
|
| + Handle<Map> new_map,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| + int field_index,
|
| + Representation representation) {
|
| + Isolate* isolate = object->GetIsolate();
|
| +
|
| // This method is used to transition to a field. If we are transitioning to a
|
| // double field, allocate new storage.
|
| - Object* storage;
|
| - MaybeObject* maybe_storage =
|
| - value->AllocateNewStorageFor(GetHeap(), representation);
|
| - if (!maybe_storage->To(&storage)) return maybe_storage;
|
| + Handle<Object> storage = NewStorageFor(isolate, value, representation);
|
|
|
| - if (map()->unused_property_fields() == 0) {
|
| + if (object->map()->unused_property_fields() == 0) {
|
| int new_unused = new_map->unused_property_fields();
|
| - FixedArray* values;
|
| - MaybeObject* maybe_values =
|
| - properties()->CopySize(properties()->length() + new_unused + 1);
|
| - if (!maybe_values->To(&values)) return maybe_values;
|
| + Handle<FixedArray> properties(object->properties());
|
| + Handle<FixedArray> values = isolate->factory()->CopySizeFixedArray(
|
| + properties, properties->length() + new_unused + 1);
|
| + object->set_properties(*values);
|
| + }
|
| +
|
| + object->set_map(*new_map);
|
| + object->FastPropertyAtPut(field_index, *storage);
|
| +}
|
| +
|
|
|
| - set_properties(values);
|
| +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;
|
| +}
|
|
|
| - set_map(new_map);
|
|
|
| - FastPropertyAtPut(field_index, storage);
|
| - return value;
|
| +static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map,
|
| + Handle<Name> name,
|
| + int index,
|
| + PropertyAttributes attributes,
|
| + Representation representation,
|
| + TransitionFlag flag) {
|
| + CALL_HEAP_FUNCTION(map->GetIsolate(),
|
| + CopyAddFieldDescriptor(
|
| + *map, *name, index, attributes, representation, flag),
|
| + Map);
|
| }
|
|
|
|
|
| -MaybeObject* JSObject::AddFastProperty(Name* name,
|
| - Object* value,
|
| - PropertyAttributes attributes,
|
| - StoreFromKeyed store_mode,
|
| - ValueType value_type,
|
| - TransitionFlag flag) {
|
| - ASSERT(!IsJSGlobalProxy());
|
| +void JSObject::AddFastProperty(Handle<JSObject> object,
|
| + Handle<Name> name,
|
| + Handle<Object> 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<Map> 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<Map> CopyAddConstantDescriptor(Handle<Map> map,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| + PropertyAttributes attributes,
|
| + TransitionFlag flag) {
|
| + CALL_HEAP_FUNCTION(map->GetIsolate(),
|
| + CopyAddConstantDescriptor(
|
| + *map, *name, *value, attributes, flag),
|
| + Map);
|
| +}
|
| +
|
|
|
| +void JSObject::AddConstantProperty(Handle<JSObject> object,
|
| + Handle<Name> name,
|
| + Handle<Object> 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<Map> 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()) {
|
| +void JSObject::AddSlowProperty(Handle<JSObject> object,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| + PropertyAttributes attributes) {
|
| + ASSERT(!object->HasFastProperties());
|
| + Isolate* isolate = object->GetIsolate();
|
| + Handle<NameDictionary> 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<PropertyCell> 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<PropertyCell> 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<NameDictionary> 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<Object> JSObject::AddProperty(Handle<JSObject> object,
|
| + Handle<Name> name,
|
| + Handle<Object> 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<Object> args[1] = {Handle<Name>(name)};
|
| - return isolate->Throw(
|
| - *isolate->factory()->NewTypeError("object_not_extensible",
|
| - HandleVector(args, 1)));
|
| + Handle<Object> args[1] = { name };
|
| + Handle<Object> error = isolate->factory()->NewTypeError(
|
| + "object_not_extensible", HandleVector(args, ARRAY_SIZE(args)));
|
| + isolate->Throw(*error);
|
| + return Handle<Object>();
|
| }
|
| }
|
|
|
| - 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<Object> 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<Object> old_value = isolate->factory()->the_hole_value();
|
| + EnqueueChangeRecord(object, "new", name, old_value);
|
| }
|
|
|
| - return *hresult;
|
| + return value;
|
| }
|
|
|
|
|
| @@ -2115,37 +2123,39 @@ void JSObject::DeliverChangeRecords(Isolate* isolate) {
|
| }
|
|
|
|
|
| -MaybeObject* JSObject::SetPropertyPostInterceptor(
|
| - Name* name,
|
| - Object* value,
|
| +Handle<Object> JSObject::SetPropertyPostInterceptor(
|
| + Handle<JSObject> object,
|
| + Handle<Name> name,
|
| + Handle<Object> 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<Object> 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 void ReplaceSlowProperty(Handle<JSObject> object,
|
| + Handle<Name> name,
|
| + Handle<Object> 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 +2163,7 @@ MaybeObject* JSObject::ReplaceSlowProperty(Name* name,
|
| }
|
|
|
| PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
|
| - return SetNormalizedProperty(name, value, new_details);
|
| + JSObject::SetNormalizedProperty(object, name, value, new_details);
|
| }
|
|
|
|
|
| @@ -2260,6 +2270,11 @@ bool Map::InstancesNeedRewriting(Map* target,
|
| }
|
|
|
|
|
| +void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> 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 +2376,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<JSObject> object,
|
| + int modify_index,
|
| + Representation new_representation,
|
| + StoreMode store_mode) {
|
| + Handle<Map> 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 +2397,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> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
|
| + int modify_index,
|
| + StoreMode store_mode,
|
| + PropertyAttributes attributes,
|
| + const char* reason) {
|
| + Handle<Map> new_map = Copy(map);
|
|
|
| DescriptorArray* descriptors = new_map->instance_descriptors();
|
| descriptors->InitializeRepresentations(Representation::Tagged());
|
| @@ -2414,7 +2424,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 +2572,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> Map::GeneralizeRepresentation(Handle<Map> old_map,
|
| + int modify_index,
|
| + Representation new_representation,
|
| + StoreMode store_mode) {
|
| + Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
|
| PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
|
| Representation old_representation = old_details.representation();
|
|
|
| @@ -2582,37 +2592,37 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
|
| }
|
|
|
| int descriptors = old_map->NumberOfOwnDescriptors();
|
| - Map* root_map = old_map->FindRootMap();
|
| + Handle<Map> 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<Map> updated(raw_updated);
|
| + Handle<DescriptorArray> 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 +2630,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<DescriptorArray> 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 +2644,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<Map> 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 +2654,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<Map> 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<Map>(new_map);
|
| - return maybe_map;
|
| - }
|
| + new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors);
|
| new_map->set_migration_target(true);
|
| }
|
|
|
| @@ -2703,94 +2704,66 @@ Map* Map::CurrentMapForDeprecated() {
|
| }
|
|
|
|
|
| -MaybeObject* JSObject::SetPropertyWithInterceptor(
|
| - Name* name,
|
| - Object* value,
|
| +Handle<Object> JSObject::SetPropertyWithInterceptor(
|
| + Handle<JSObject> object,
|
| + Handle<Name> name,
|
| + Handle<Object> 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<JSObject> this_handle(this);
|
| - Handle<String> name_handle(String::cast(name));
|
| - Handle<Object> value_handle(value, isolate);
|
| - Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
|
| + Isolate* isolate = object->GetIsolate();
|
| + Handle<String> name_string = Handle<String>::cast(name);
|
| + Handle<InterceptorInfo> 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<v8::NamedPropertySetterCallback>(interceptor->setter());
|
| - Handle<Object> value_unhole(value->IsTheHole() ?
|
| - isolate->heap()->undefined_value() :
|
| - value,
|
| - isolate);
|
| + Handle<Object> value_unhole = value->IsTheHole()
|
| + ? Handle<Object>(isolate->factory()->undefined_value()) : value;
|
| v8::Handle<v8::Value> 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<Object> result =
|
| + SetPropertyPostInterceptor(object, name, value, attributes, strict_mode);
|
| + RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| + return result;
|
| }
|
|
|
|
|
| Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
|
| - Handle<Name> key,
|
| + Handle<Name> name,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode) {
|
| - CALL_HEAP_FUNCTION(object->GetIsolate(),
|
| - object->SetProperty(*key, *value, attributes, strict_mode),
|
| - Object);
|
| -}
|
| -
|
| -
|
| -MaybeObject* JSReceiver::SetPropertyOrFail(
|
| - Handle<JSReceiver> object,
|
| - Handle<Name> key,
|
| - Handle<Object> 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);
|
| }
|
|
|
|
|
| -MaybeObject* JSObject::SetPropertyWithCallback(Object* structure,
|
| - Name* name,
|
| - Object* value,
|
| - JSObject* holder,
|
| - StrictModeFlag strict_mode) {
|
| - Isolate* isolate = GetIsolate();
|
| - HandleScope scope(isolate);
|
| +Handle<Object> JSObject::SetPropertyWithCallback(Handle<JSObject> object,
|
| + Handle<Object> structure,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| + Handle<JSObject> holder,
|
| + StrictModeFlag strict_mode) {
|
| + Isolate* isolate = object->GetIsolate();
|
|
|
| // We should never get here to initialize a const with the hole
|
| // value since a const declaration would conflict with the setter.
|
| ASSERT(!value->IsTheHole());
|
| - Handle<Object> value_handle(value, isolate);
|
|
|
| // To accommodate both the old and the new api we switch on the
|
| // data structure used to store the callbacks. Eventually foreign
|
| @@ -2798,26 +2771,27 @@ MaybeObject* JSObject::SetPropertyWithCallback(Object* structure,
|
| if (structure->IsForeign()) {
|
| AccessorDescriptor* callback =
|
| reinterpret_cast<AccessorDescriptor*>(
|
| - Foreign::cast(structure)->foreign_address());
|
| - MaybeObject* obj = (callback->setter)(
|
| - isolate, this, value, callback->data);
|
| - RETURN_IF_SCHEDULED_EXCEPTION(isolate);
|
| - if (obj->IsFailure()) return obj;
|
| - return *value_handle;
|
| + Handle<Foreign>::cast(structure)->foreign_address());
|
| + CALL_AND_RETRY_OR_DIE(isolate,
|
| + (callback->setter)(
|
| + isolate, *object, *value, callback->data),
|
| + break,
|
| + return Handle<Object>());
|
| + RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| + return value;
|
| }
|
|
|
| if (structure->IsExecutableAccessorInfo()) {
|
| // api style callbacks
|
| - ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(structure);
|
| - if (!data->IsCompatibleReceiver(this)) {
|
| - Handle<Object> name_handle(name, isolate);
|
| - Handle<Object> receiver_handle(this, isolate);
|
| - Handle<Object> args[2] = { name_handle, receiver_handle };
|
| + ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure);
|
| + if (!data->IsCompatibleReceiver(*object)) {
|
| + Handle<Object> args[2] = { name, object };
|
| Handle<Object> error =
|
| isolate->factory()->NewTypeError("incompatible_method_receiver",
|
| HandleVector(args,
|
| ARRAY_SIZE(args)));
|
| - return isolate->Throw(*error);
|
| + isolate->Throw(*error);
|
| + return Handle<Object>();
|
| }
|
| // TODO(rossberg): Support symbols in the API.
|
| if (name->IsSymbol()) return value;
|
| @@ -2825,32 +2799,33 @@ MaybeObject* JSObject::SetPropertyWithCallback(Object* structure,
|
| v8::AccessorSetterCallback call_fun =
|
| v8::ToCData<v8::AccessorSetterCallback>(call_obj);
|
| if (call_fun == NULL) return value;
|
| - Handle<String> key(String::cast(name));
|
| - LOG(isolate, ApiNamedPropertyAccess("store", this, name));
|
| + Handle<String> key = Handle<String>::cast(name);
|
| + LOG(isolate, ApiNamedPropertyAccess("store", *object, *name));
|
| PropertyCallbackArguments args(
|
| - isolate, data->data(), this, JSObject::cast(holder));
|
| + isolate, data->data(), *object, JSObject::cast(*holder));
|
| args.Call(call_fun,
|
| v8::Utils::ToLocal(key),
|
| - v8::Utils::ToLocal(value_handle));
|
| - RETURN_IF_SCHEDULED_EXCEPTION(isolate);
|
| - return *value_handle;
|
| + v8::Utils::ToLocal(value));
|
| + RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| + return value;
|
| }
|
|
|
| if (structure->IsAccessorPair()) {
|
| - Object* setter = AccessorPair::cast(structure)->setter();
|
| + Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
|
| if (setter->IsSpecFunction()) {
|
| // TODO(rossberg): nicer would be to cast to some JSCallable here...
|
| - return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value);
|
| + return SetPropertyWithDefinedSetter(
|
| + object, Handle<JSReceiver>::cast(setter), value);
|
| } else {
|
| if (strict_mode == kNonStrictMode) {
|
| return value;
|
| }
|
| - Handle<Name> key(name);
|
| - Handle<Object> holder_handle(holder, isolate);
|
| - Handle<Object> args[2] = { key, holder_handle };
|
| - return isolate->Throw(
|
| - *isolate->factory()->NewTypeError("no_setter_in_callback",
|
| - HandleVector(args, 2)));
|
| + Handle<Object> args[2] = { name, holder };
|
| + Handle<Object> error =
|
| + isolate->factory()->NewTypeError("no_setter_in_callback",
|
| + HandleVector(args, 2));
|
| + isolate->Throw(*error);
|
| + return Handle<Object>();
|
| }
|
| }
|
|
|
| @@ -2860,32 +2835,33 @@ MaybeObject* JSObject::SetPropertyWithCallback(Object* structure,
|
| }
|
|
|
| UNREACHABLE();
|
| - return NULL;
|
| + return Handle<Object>();
|
| }
|
|
|
|
|
| -MaybeObject* JSReceiver::SetPropertyWithDefinedSetter(JSReceiver* setter,
|
| - Object* value) {
|
| - Isolate* isolate = GetIsolate();
|
| - Handle<Object> value_handle(value, isolate);
|
| - Handle<JSReceiver> fun(setter, isolate);
|
| - Handle<JSReceiver> self(this, isolate);
|
| +Handle<Object> JSReceiver::SetPropertyWithDefinedSetter(
|
| + Handle<JSReceiver> object,
|
| + Handle<JSReceiver> setter,
|
| + Handle<Object> value) {
|
| + Isolate* isolate = object->GetIsolate();
|
| +
|
| #ifdef ENABLE_DEBUGGER_SUPPORT
|
| Debug* debug = isolate->debug();
|
| // Handle stepping into a setter if step into is active.
|
| // TODO(rossberg): should this apply to getters that are function proxies?
|
| - if (debug->StepInActive() && fun->IsJSFunction()) {
|
| + if (debug->StepInActive() && setter->IsJSFunction()) {
|
| debug->HandleStepIn(
|
| - Handle<JSFunction>::cast(fun), Handle<Object>::null(), 0, false);
|
| + Handle<JSFunction>::cast(setter), Handle<Object>::null(), 0, false);
|
| }
|
| #endif
|
| +
|
| bool has_pending_exception;
|
| - Handle<Object> argv[] = { value_handle };
|
| + Handle<Object> argv[] = { value };
|
| Execution::Call(
|
| - isolate, fun, self, ARRAY_SIZE(argv), argv, &has_pending_exception);
|
| + isolate, setter, object, ARRAY_SIZE(argv), argv, &has_pending_exception);
|
| // Check for pending exception and return the result.
|
| - if (has_pending_exception) return Failure::Exception();
|
| - return *value_handle;
|
| + if (has_pending_exception) return Handle<Object>();
|
| + return value;
|
| }
|
|
|
|
|
| @@ -2899,14 +2875,16 @@ MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
|
| pt != heap->null_value();
|
| pt = pt->GetPrototype(GetIsolate())) {
|
| if (pt->IsJSProxy()) {
|
| - String* name;
|
| - MaybeObject* maybe = heap->Uint32ToString(index);
|
| - if (!maybe->To<String>(&name)) {
|
| - *found = true; // Force abort
|
| - return maybe;
|
| - }
|
| - return JSProxy::cast(pt)->SetPropertyViaPrototypesWithHandler(
|
| - this, name, value, NONE, strict_mode, found);
|
| + Isolate* isolate = GetIsolate();
|
| + HandleScope scope(isolate);
|
| + Handle<JSProxy> proxy(JSProxy::cast(pt));
|
| + Handle<JSObject> self(this, isolate);
|
| + Handle<String> name = isolate->factory()->Uint32ToString(index);
|
| + Handle<Object> value_handle(value, isolate);
|
| + Handle<Object> 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()) {
|
| continue;
|
| @@ -2918,11 +2896,16 @@ MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
|
| PropertyDetails details = dictionary->DetailsAt(entry);
|
| if (details.type() == CALLBACKS) {
|
| *found = true;
|
| - return SetElementWithCallback(dictionary->ValueAt(entry),
|
| - index,
|
| - value,
|
| - JSObject::cast(pt),
|
| - strict_mode);
|
| + Isolate* isolate = GetIsolate();
|
| + HandleScope scope(isolate);
|
| + Handle<JSObject> self(this, isolate);
|
| + Handle<Object> structure(dictionary->ValueAt(entry), isolate);
|
| + Handle<Object> value_handle(value, isolate);
|
| + Handle<JSObject> holder(JSObject::cast(pt));
|
| + Handle<Object> result = SetElementWithCallback(
|
| + self, structure, index, value_handle, holder, strict_mode);
|
| + RETURN_IF_EMPTY_HANDLE(isolate, result);
|
| + return *result;
|
| }
|
| }
|
| }
|
| @@ -2930,21 +2913,21 @@ 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<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object,
|
| + Handle<Name> name,
|
| + Handle<Object> 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 +2938,21 @@ 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);
|
| + Handle<Object> callback_object(result.GetCallbackObject(), isolate);
|
| + return SetPropertyWithCallback(object, callback_object, name, value,
|
| + handle(result.holder()), strict_mode);
|
| }
|
| case HANDLER: {
|
| - return result.proxy()->SetPropertyViaPrototypesWithHandler(
|
| - this, name, value, attributes, strict_mode, done);
|
| + Handle<JSProxy> proxy(result.proxy());
|
| + return JSProxy::SetPropertyViaPrototypesWithHandler(
|
| + proxy, object, name, value, attributes, strict_mode, done);
|
| }
|
| case TRANSITION:
|
| case NONEXISTENT:
|
| @@ -2980,12 +2965,13 @@ MaybeObject* JSObject::SetPropertyViaPrototypes(
|
| if (!FLAG_es5_readonly) *done = false;
|
| if (*done) {
|
| if (strict_mode == kNonStrictMode) return value;
|
| - Handle<Object> args[] = { Handle<Object>(name, isolate),
|
| - Handle<Object>(this, isolate)};
|
| - return isolate->Throw(*isolate->factory()->NewTypeError(
|
| - "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
|
| + Handle<Object> args[] = { name, object };
|
| + Handle<Object> error = isolate->factory()->NewTypeError(
|
| + "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
|
| + isolate->Throw(*error);
|
| + return Handle<Object>();
|
| }
|
| - return heap->the_hole_value();
|
| + return isolate->factory()->the_hole_value();
|
| }
|
|
|
|
|
| @@ -3340,14 +3326,15 @@ void JSObject::LookupRealNamedPropertyInPrototypes(Name* name,
|
|
|
|
|
| // We only need to deal with CALLBACKS and INTERCEPTORS
|
| -MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
|
| +Handle<Object> JSObject::SetPropertyWithFailedAccessCheck(
|
| + Handle<JSObject> object,
|
| LookupResult* result,
|
| - Name* name,
|
| - Object* value,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| bool check_prototype,
|
| StrictModeFlag strict_mode) {
|
| if (check_prototype && !result->IsProperty()) {
|
| - LookupRealNamedPropertyInPrototypes(name, result);
|
| + object->LookupRealNamedPropertyInPrototypes(*name, result);
|
| }
|
|
|
| if (result->IsProperty()) {
|
| @@ -3356,21 +3343,23 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
|
| case CALLBACKS: {
|
| Object* obj = result->GetCallbackObject();
|
| if (obj->IsAccessorInfo()) {
|
| - AccessorInfo* info = AccessorInfo::cast(obj);
|
| + Handle<AccessorInfo> info(AccessorInfo::cast(obj));
|
| if (info->all_can_write()) {
|
| - return SetPropertyWithCallback(result->GetCallbackObject(),
|
| + return SetPropertyWithCallback(object,
|
| + info,
|
| name,
|
| value,
|
| - result->holder(),
|
| + handle(result->holder()),
|
| strict_mode);
|
| }
|
| } else if (obj->IsAccessorPair()) {
|
| - AccessorPair* pair = AccessorPair::cast(obj);
|
| + Handle<AccessorPair> pair(AccessorPair::cast(obj));
|
| if (pair->all_can_read()) {
|
| - return SetPropertyWithCallback(result->GetCallbackObject(),
|
| + return SetPropertyWithCallback(object,
|
| + pair,
|
| name,
|
| value,
|
| - result->holder(),
|
| + handle(result->holder()),
|
| strict_mode);
|
| }
|
| }
|
| @@ -3379,10 +3368,11 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
|
| case INTERCEPTOR: {
|
| // Try lookup real named properties. Note that only property can be
|
| // set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
|
| - LookupResult r(GetIsolate());
|
| - LookupRealNamedProperty(name, &r);
|
| + LookupResult r(object->GetIsolate());
|
| + object->LookupRealNamedProperty(*name, &r);
|
| if (r.IsProperty()) {
|
| - return SetPropertyWithFailedAccessCheck(&r,
|
| + return SetPropertyWithFailedAccessCheck(object,
|
| + &r,
|
| name,
|
| value,
|
| check_prototype,
|
| @@ -3397,42 +3387,38 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
|
| }
|
| }
|
|
|
| - Isolate* isolate = GetIsolate();
|
| - HandleScope scope(isolate);
|
| - Handle<Object> value_handle(value, isolate);
|
| - isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
|
| - RETURN_IF_SCHEDULED_EXCEPTION(isolate);
|
| - return *value_handle;
|
| + Isolate* isolate = object->GetIsolate();
|
| + isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET);
|
| + RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| + return value;
|
| }
|
|
|
|
|
| -MaybeObject* JSReceiver::SetProperty(LookupResult* result,
|
| - Name* key,
|
| - Object* value,
|
| - PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| - JSReceiver::StoreFromKeyed store_mode) {
|
| +Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
|
| + LookupResult* result,
|
| + Handle<Name> key,
|
| + Handle<Object> 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<JSObject>::cast(object),
|
| result, key, value, attributes, strict_mode, store_mode);
|
| }
|
| }
|
|
|
|
|
| -bool JSProxy::HasPropertyWithHandler(Name* name_raw) {
|
| - Isolate* isolate = GetIsolate();
|
| - HandleScope scope(isolate);
|
| - Handle<Object> receiver(this, isolate);
|
| - Handle<Object> name(name_raw, isolate);
|
| +bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) {
|
| + Isolate* isolate = proxy->GetIsolate();
|
|
|
| // TODO(rossberg): adjust once there is a story for symbols vs proxies.
|
| if (name->IsSymbol()) return false;
|
|
|
| Handle<Object> args[] = { name };
|
| - Handle<Object> result = CallTrap(
|
| + Handle<Object> result = proxy->CallTrap(
|
| "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args);
|
| if (isolate->has_pending_exception()) return false;
|
|
|
| @@ -3440,58 +3426,51 @@ 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<JSReceiver> receiver(receiver_raw);
|
| - Handle<Object> name(name_raw, isolate);
|
| - Handle<Object> value(value_raw, isolate);
|
| +Handle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy,
|
| + Handle<JSReceiver> receiver,
|
| + Handle<Name> name,
|
| + Handle<Object> 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<Object> 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<Object>();
|
|
|
| - return *value;
|
| + return value;
|
| }
|
|
|
|
|
| -MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
|
| - JSReceiver* receiver_raw,
|
| - Name* name_raw,
|
| - Object* value_raw,
|
| +Handle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
|
| + Handle<JSProxy> proxy,
|
| + Handle<JSReceiver> receiver,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| PropertyAttributes attributes,
|
| StrictModeFlag strict_mode,
|
| bool* done) {
|
| - Isolate* isolate = GetIsolate();
|
| - Handle<JSProxy> proxy(this);
|
| - Handle<JSReceiver> receiver(receiver_raw);
|
| - Handle<Name> name(name_raw);
|
| - Handle<Object> value(value_raw, isolate);
|
| - Handle<Object> handler(this->handler(), isolate); // Trap might morph proxy.
|
| + Isolate* isolate = proxy->GetIsolate();
|
| + Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy.
|
|
|
| // TODO(rossberg): adjust once there is a story for symbols vs proxies.
|
| if (name->IsSymbol()) {
|
| *done = false;
|
| - return isolate->heap()->the_hole_value();
|
| + return isolate->factory()->the_hole_value();
|
| }
|
|
|
| *done = true; // except where redefined...
|
| Handle<Object> args[] = { name };
|
| Handle<Object> result = proxy->CallTrap(
|
| "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
|
| - if (isolate->has_pending_exception()) return Failure::Exception();
|
| + if (isolate->has_pending_exception()) return Handle<Object>();
|
|
|
| if (result->IsUndefined()) {
|
| *done = false;
|
| - return isolate->heap()->the_hole_value();
|
| + return isolate->factory()->the_hole_value();
|
| }
|
|
|
| // Emulate [[GetProperty]] semantics for proxies.
|
| @@ -3500,7 +3479,7 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
|
| Handle<Object> desc = Execution::Call(
|
| isolate, isolate->to_complete_property_descriptor(), result,
|
| ARRAY_SIZE(argv), argv, &has_pending_exception);
|
| - if (has_pending_exception) return Failure::Exception();
|
| + if (has_pending_exception) return Handle<Object>();
|
|
|
| // [[GetProperty]] requires to check that all properties are configurable.
|
| Handle<String> configurable_name =
|
| @@ -3517,7 +3496,8 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
|
| Handle<Object> args[] = { handler, trap, name };
|
| Handle<Object> error = isolate->factory()->NewTypeError(
|
| "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
|
| - return isolate->Throw(*error);
|
| + isolate->Throw(*error);
|
| + return Handle<Object>();
|
| }
|
| ASSERT(configurable->IsTrue());
|
|
|
| @@ -3538,12 +3518,13 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
|
| ASSERT(!isolate->has_pending_exception());
|
| ASSERT(writable->IsTrue() || writable->IsFalse());
|
| *done = writable->IsFalse();
|
| - if (!*done) return GetHeap()->the_hole_value();
|
| - if (strict_mode == kNonStrictMode) return *value;
|
| + if (!*done) return isolate->factory()->the_hole_value();
|
| + if (strict_mode == kNonStrictMode) return value;
|
| Handle<Object> args[] = { name, receiver };
|
| Handle<Object> error = isolate->factory()->NewTypeError(
|
| "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
|
| - return isolate->Throw(*error);
|
| + isolate->Throw(*error);
|
| + return Handle<Object>();
|
| }
|
|
|
| // We have an AccessorDescriptor.
|
| @@ -3553,15 +3534,16 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
|
| ASSERT(!isolate->has_pending_exception());
|
| if (!setter->IsUndefined()) {
|
| // TODO(rossberg): nicer would be to cast to some JSCallable here...
|
| - return receiver->SetPropertyWithDefinedSetter(
|
| - JSReceiver::cast(*setter), *value);
|
| + return SetPropertyWithDefinedSetter(
|
| + receiver, Handle<JSReceiver>::cast(setter), value);
|
| }
|
|
|
| - if (strict_mode == kNonStrictMode) return *value;
|
| + if (strict_mode == kNonStrictMode) return value;
|
| Handle<Object> args2[] = { name, proxy };
|
| Handle<Object> error = isolate->factory()->NewTypeError(
|
| "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2)));
|
| - return isolate->Throw(*error);
|
| + isolate->Throw(*error);
|
| + return Handle<Object>();
|
| }
|
|
|
|
|
| @@ -3734,36 +3716,31 @@ void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
|
|
|
|
|
| void JSObject::MigrateInstance(Handle<JSObject> 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<Map> original_map(object->map());
|
| + GeneralizeFieldRepresentation(
|
| + object, 0, Representation::None(), ALLOW_AS_CONSTANT);
|
| + if (FLAG_trace_migration) {
|
| + object->PrintInstanceMigration(stdout, *original_map, object->map());
|
| + }
|
| }
|
|
|
|
|
| Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) {
|
| - CALL_HEAP_FUNCTION(
|
| - object->GetIsolate(),
|
| - object->MigrateInstance(),
|
| - Object);
|
| -}
|
| -
|
| -
|
| -Handle<Map> Map::GeneralizeRepresentation(Handle<Map> 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> name,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes) {
|
| - Map* transition_map = lookup->GetTransitionTarget();
|
| +Handle<Object> JSObject::SetPropertyUsingTransition(
|
| + Handle<JSObject> object,
|
| + LookupResult* lookup,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| + PropertyAttributes attributes) {
|
| + Handle<Map> transition_map(lookup->GetTransitionTarget());
|
| int descriptor = transition_map->LastAdded();
|
|
|
| DescriptorArray* descriptors = transition_map->instance_descriptors();
|
| @@ -3773,8 +3750,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 +3762,41 @@ 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);
|
| + AddFastPropertyUsingMap(
|
| + object, transition_map, name, value, field_index, representation);
|
| + return value;
|
| }
|
|
|
|
|
| -static MaybeObject* SetPropertyToField(LookupResult* lookup,
|
| - Handle<Name> name,
|
| - Handle<Object> value) {
|
| +static void SetPropertyToField(LookupResult* lookup,
|
| + Handle<Name> name,
|
| + Handle<Object> 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 +3806,180 @@ static MaybeObject* SetPropertyToField(LookupResult* lookup,
|
| HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt(
|
| lookup->GetFieldIndex().field_index()));
|
| storage->set_value(value->Number());
|
| - return *value;
|
| + return;
|
| }
|
|
|
| lookup->holder()->FastPropertyAtPut(
|
| lookup->GetFieldIndex().field_index(), *value);
|
| - return *value;
|
| }
|
|
|
|
|
| -static MaybeObject* ConvertAndSetLocalProperty(LookupResult* lookup,
|
| - Name* name,
|
| - Object* value,
|
| - PropertyAttributes attributes) {
|
| - JSObject* object = lookup->holder();
|
| +static void ConvertAndSetLocalProperty(LookupResult* lookup,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| + PropertyAttributes attributes) {
|
| + Handle<JSObject> 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);
|
| + ReplaceSlowProperty(object, name, value, attributes);
|
| + return;
|
| }
|
|
|
| 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<Map> old_map(object->map());
|
| + Handle<Map> 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);
|
| - return value;
|
| + object->FastPropertyAtPut(index, *value);
|
| }
|
|
|
|
|
| -static MaybeObject* SetPropertyToFieldWithAttributes(
|
| - LookupResult* lookup,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes) {
|
| +static void SetPropertyToFieldWithAttributes(LookupResult* lookup,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| + PropertyAttributes attributes) {
|
| if (lookup->GetAttributes() == attributes) {
|
| - if (value->IsUninitialized()) return *value;
|
| - return SetPropertyToField(lookup, name, value);
|
| + if (value->IsUninitialized()) return;
|
| + SetPropertyToField(lookup, name, value);
|
| } else {
|
| - return ConvertAndSetLocalProperty(lookup, *name, *value, attributes);
|
| + 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<Object> JSObject::SetPropertyForResult(Handle<JSObject> object,
|
| + LookupResult* lookup,
|
| + Handle<Name> name,
|
| + Handle<Object> 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<String>::cast(name)->length() <= 2) {
|
| + name = isolate->factory()->InternalizeString(Handle<String>::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)) {
|
| + return SetPropertyWithFailedAccessCheck(object, lookup, name, value,
|
| + true, strict_mode);
|
| }
|
| }
|
|
|
| - if (IsJSGlobalProxy()) {
|
| - Object* proto = GetPrototype();
|
| - if (proto->IsNull()) return value_raw;
|
| + if (object->IsJSGlobalProxy()) {
|
| + Handle<Object> 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<JSObject>::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<JSObject> self(this);
|
| - Handle<Name> name(name_raw);
|
| - Handle<Object> 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<Object> 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<Object> args[] = { name, self };
|
| - return isolate->Throw(*isolate->factory()->NewTypeError(
|
| - "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
|
| + Handle<Object> args[] = { name, object };
|
| + Handle<Object> error = isolate->factory()->NewTypeError(
|
| + "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
|
| + isolate->Throw(*error);
|
| + return Handle<Object>();
|
| } else {
|
| - return *value;
|
| + return value;
|
| }
|
| }
|
|
|
| - Handle<Object> old_value(heap->the_hole_value(), isolate);
|
| + Handle<Object> 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<Object> result = value;
|
| switch (lookup->type()) {
|
| case NORMAL:
|
| - result = lookup->holder()->SetNormalizedProperty(lookup, *value);
|
| + SetNormalizedProperty(handle(lookup->holder()), lookup, value);
|
| break;
|
| case FIELD:
|
| - result = SetPropertyToField(lookup, name, value);
|
| + SetPropertyToField(lookup, name, value);
|
| break;
|
| case CONSTANT:
|
| // Only replace the constant if necessary.
|
| - if (*value == lookup->GetConstant()) return *value;
|
| - result = SetPropertyToField(lookup, name, value);
|
| + if (*value == lookup->GetConstant()) return value;
|
| + SetPropertyToField(lookup, name, value);
|
| break;
|
| case CALLBACKS: {
|
| - Object* callback_object = lookup->GetCallbackObject();
|
| - return self->SetPropertyWithCallback(
|
| - callback_object, *name, *value, lookup->holder(), strict_mode);
|
| + Handle<Object> callback_object(lookup->GetCallbackObject(), isolate);
|
| + return SetPropertyWithCallback(object, callback_object, name, value,
|
| + handle(lookup->holder()), strict_mode);
|
| }
|
| 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<Object> hresult;
|
| - if (!result->ToHandle(&hresult, isolate)) return result;
|
| + RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
|
|
|
| - 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<Object> new_value = Object::GetProperty(self, name);
|
| + Handle<Object> 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,142 +4017,114 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributesTrampoline(
|
| // doesn't handle function prototypes correctly.
|
| Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
|
| Handle<JSObject> object,
|
| - Handle<Name> key,
|
| + Handle<Name> name,
|
| Handle<Object> 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)) {
|
| + return SetPropertyWithFailedAccessCheck(object, &lookup, name, value,
|
| + false, kNonStrictMode);
|
| }
|
| }
|
|
|
| - if (IsJSGlobalProxy()) {
|
| - Object* proto = GetPrototype();
|
| - if (proto->IsNull()) return value_raw;
|
| + if (object->IsJSGlobalProxy()) {
|
| + Handle<Object> 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<JSObject>::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<JSObject> self(this);
|
| - Handle<Name> name(name_raw);
|
| - Handle<Object> value(value_raw, isolate);
|
| -
|
| - Handle<Object> old_value(isolate->heap()->the_hole_value(), isolate);
|
| + Handle<Object> 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;
|
| switch (lookup.type()) {
|
| case NORMAL:
|
| - result = self->ReplaceSlowProperty(*name, *value, attributes);
|
| + ReplaceSlowProperty(object, name, value, attributes);
|
| break;
|
| case FIELD:
|
| - result = SetPropertyToFieldWithAttributes(
|
| - &lookup, name, value, attributes);
|
| + SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
|
| break;
|
| case CONSTANT:
|
| // Only replace the constant if necessary.
|
| if (lookup.GetAttributes() != attributes ||
|
| *value != lookup.GetConstant()) {
|
| - result = SetPropertyToFieldWithAttributes(
|
| - &lookup, name, value, attributes);
|
| + SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
|
| }
|
| break;
|
| case CALLBACKS:
|
| - result = ConvertAndSetLocalProperty(&lookup, *name, *value, attributes);
|
| + ConvertAndSetLocalProperty(&lookup, name, value, attributes);
|
| break;
|
| - case TRANSITION:
|
| - result = SetPropertyUsingTransition(&lookup, name, value, attributes);
|
| + case TRANSITION: {
|
| + Handle<Object> result = SetPropertyUsingTransition(
|
| + handle(lookup.holder()), &lookup, name, value, attributes);
|
| + RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
|
| break;
|
| + }
|
| case NONEXISTENT:
|
| case HANDLER:
|
| case INTERCEPTOR:
|
| UNREACHABLE();
|
| }
|
|
|
| - Handle<Object> hresult;
|
| - if (!result->ToHandle(&hresult, isolate)) 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<Object> new_value = Object::GetProperty(self, name);
|
| + Handle<Object> 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 value;
|
| }
|
|
|
|
|
| @@ -4667,6 +4593,18 @@ static MUST_USE_RESULT MaybeObject* CopyFastElementsToDictionary(
|
| }
|
|
|
|
|
| +static Handle<SeededNumberDictionary> CopyFastElementsToDictionary(
|
| + Handle<FixedArrayBase> array,
|
| + int length,
|
| + Handle<SeededNumberDictionary> dict) {
|
| + Isolate* isolate = array->GetIsolate();
|
| + CALL_HEAP_FUNCTION(isolate,
|
| + CopyFastElementsToDictionary(
|
| + isolate, *array, length, *dict),
|
| + SeededNumberDictionary);
|
| +}
|
| +
|
| +
|
| Handle<SeededNumberDictionary> JSObject::NormalizeElements(
|
| Handle<JSObject> object) {
|
| CALL_HEAP_FUNCTION(object->GetIsolate(),
|
| @@ -5152,7 +5090,7 @@ Handle<Object> JSObject::DeleteElement(Handle<JSObject> object,
|
| Handle<Object> old_value;
|
| bool should_enqueue_change_record = false;
|
| if (FLAG_harmony_observation && object->map()->is_observed()) {
|
| - should_enqueue_change_record = object->HasLocalElement(index);
|
| + should_enqueue_change_record = HasLocalElement(object, index);
|
| if (should_enqueue_change_record) {
|
| old_value = object->GetLocalElementAccessorPair(index) != NULL
|
| ? Handle<Object>::cast(factory->the_hole_value())
|
| @@ -5168,7 +5106,7 @@ Handle<Object> JSObject::DeleteElement(Handle<JSObject> object,
|
| result = AccessorDelete(object, index, mode);
|
| }
|
|
|
| - if (should_enqueue_change_record && !object->HasLocalElement(index)) {
|
| + if (should_enqueue_change_record && !HasLocalElement(object, index)) {
|
| Handle<String> name = factory->Uint32ToString(index);
|
| EnqueueChangeRecord(object, "deleted", name, old_value);
|
| }
|
| @@ -5243,7 +5181,7 @@ Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
|
| result = DeleteNormalizedProperty(object, name, mode);
|
| }
|
|
|
| - if (is_observed && !object->HasLocalProperty(*name)) {
|
| + if (is_observed && !HasLocalProperty(object, name)) {
|
| EnqueueChangeRecord(object, "deleted", name, old_value);
|
| }
|
|
|
| @@ -5482,122 +5420,114 @@ static void FreezeDictionary(Dictionary* dictionary) {
|
| }
|
|
|
|
|
| -MUST_USE_RESULT MaybeObject* JSObject::Freeze(Isolate* isolate) {
|
| +Handle<Object> JSObject::Freeze(Handle<JSObject> object) {
|
| // Freezing non-strict arguments should be handled elsewhere.
|
| - ASSERT(!HasNonStrictArgumentsElements());
|
| -
|
| - Heap* heap = isolate->heap();
|
| + ASSERT(!object->HasNonStrictArgumentsElements());
|
|
|
| - if (map()->is_frozen()) return this;
|
| + if (object->map()->is_frozen()) return object;
|
|
|
| - if (IsAccessCheckNeeded() &&
|
| - !isolate->MayNamedAccess(this,
|
| - heap->undefined_value(),
|
| + Isolate* isolate = object->GetIsolate();
|
| + if (object->IsAccessCheckNeeded() &&
|
| + !isolate->MayNamedAccess(*object,
|
| + isolate->heap()->undefined_value(),
|
| v8::ACCESS_KEYS)) {
|
| - isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
|
| - RETURN_IF_SCHEDULED_EXCEPTION(isolate);
|
| - return heap->false_value();
|
| + isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
|
| + RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| + return isolate->factory()->false_value();
|
| }
|
|
|
| - if (IsJSGlobalProxy()) {
|
| - Object* proto = GetPrototype();
|
| - if (proto->IsNull()) return this;
|
| + if (object->IsJSGlobalProxy()) {
|
| + Handle<Object> proto(object->GetPrototype(), isolate);
|
| + if (proto->IsNull()) return object;
|
| ASSERT(proto->IsJSGlobalObject());
|
| - return JSObject::cast(proto)->Freeze(isolate);
|
| + return Freeze(Handle<JSObject>::cast(proto));
|
| }
|
|
|
| // It's not possible to freeze objects with external array elements
|
| - if (HasExternalArrayElements()) {
|
| - HandleScope scope(isolate);
|
| - Handle<Object> object(this, isolate);
|
| + if (object->HasExternalArrayElements()) {
|
| Handle<Object> error =
|
| isolate->factory()->NewTypeError(
|
| "cant_prevent_ext_external_array_elements",
|
| HandleVector(&object, 1));
|
| - return isolate->Throw(*error);
|
| + isolate->Throw(*error);
|
| + return Handle<Object>();
|
| }
|
|
|
| - SeededNumberDictionary* new_element_dictionary = NULL;
|
| - if (!elements()->IsDictionary()) {
|
| - int length = IsJSArray()
|
| - ? Smi::cast(JSArray::cast(this)->length())->value()
|
| - : elements()->length();
|
| + Handle<SeededNumberDictionary> new_element_dictionary;
|
| + if (!object->elements()->IsDictionary()) {
|
| + int length = object->IsJSArray()
|
| + ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
|
| + : object->elements()->length();
|
| if (length > 0) {
|
| int capacity = 0;
|
| int used = 0;
|
| - GetElementsCapacityAndUsage(&capacity, &used);
|
| - MaybeObject* maybe_dict = SeededNumberDictionary::Allocate(heap, used);
|
| - if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict;
|
| + object->GetElementsCapacityAndUsage(&capacity, &used);
|
| + new_element_dictionary =
|
| + isolate->factory()->NewSeededNumberDictionary(used);
|
|
|
| // Move elements to a dictionary; avoid calling NormalizeElements to avoid
|
| // unnecessary transitions.
|
| - maybe_dict = CopyFastElementsToDictionary(isolate, elements(), length,
|
| - new_element_dictionary);
|
| - if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict;
|
| + new_element_dictionary = CopyFastElementsToDictionary(
|
| + handle(object->elements()), length, new_element_dictionary);
|
| } else {
|
| // No existing elements, use a pre-allocated empty backing store
|
| - new_element_dictionary = heap->empty_slow_element_dictionary();
|
| + new_element_dictionary =
|
| + isolate->factory()->empty_slow_element_dictionary();
|
| }
|
| }
|
|
|
| LookupResult result(isolate);
|
| - map()->LookupTransition(this, heap->frozen_symbol(), &result);
|
| + Handle<Map> old_map(object->map());
|
| + old_map->LookupTransition(*object, isolate->heap()->frozen_symbol(), &result);
|
| if (result.IsTransition()) {
|
| Map* transition_map = result.GetTransitionTarget();
|
| ASSERT(transition_map->has_dictionary_elements());
|
| ASSERT(transition_map->is_frozen());
|
| ASSERT(!transition_map->is_extensible());
|
| - set_map(transition_map);
|
| - } else if (HasFastProperties() && map()->CanHaveMoreTransitions()) {
|
| + object->set_map(transition_map);
|
| + } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
|
| // Create a new descriptor array with fully-frozen properties
|
| - int num_descriptors = map()->NumberOfOwnDescriptors();
|
| - DescriptorArray* new_descriptors;
|
| - MaybeObject* maybe_descriptors =
|
| - map()->instance_descriptors()->CopyUpToAddAttributes(num_descriptors,
|
| - FROZEN);
|
| - if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
|
| -
|
| - Map* new_map;
|
| - MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors(
|
| - new_descriptors, INSERT_TRANSITION, heap->frozen_symbol());
|
| - if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
| + int num_descriptors = old_map->NumberOfOwnDescriptors();
|
| + Handle<DescriptorArray> new_descriptors =
|
| + DescriptorArray::CopyUpToAddAttributes(
|
| + handle(old_map->instance_descriptors()), num_descriptors, FROZEN);
|
| + Handle<Map> new_map = Map::CopyReplaceDescriptors(
|
| + old_map, new_descriptors, INSERT_TRANSITION,
|
| + isolate->factory()->frozen_symbol());
|
| new_map->freeze();
|
| new_map->set_is_extensible(false);
|
| new_map->set_elements_kind(DICTIONARY_ELEMENTS);
|
| - set_map(new_map);
|
| + object->set_map(*new_map);
|
| } else {
|
| // Slow path: need to normalize properties for safety
|
| - MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
|
| - if (maybe->IsFailure()) return maybe;
|
| + NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
|
|
|
| // Create a new map, since other objects with this map may be extensible.
|
| // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
|
| - Map* new_map;
|
| - MaybeObject* maybe_copy = map()->Copy();
|
| - if (!maybe_copy->To(&new_map)) return maybe_copy;
|
| + Handle<Map> new_map = Map::Copy(handle(object->map()));
|
| new_map->freeze();
|
| new_map->set_is_extensible(false);
|
| new_map->set_elements_kind(DICTIONARY_ELEMENTS);
|
| - set_map(new_map);
|
| + object->set_map(*new_map);
|
|
|
| // Freeze dictionary-mode properties
|
| - FreezeDictionary(property_dictionary());
|
| + FreezeDictionary(object->property_dictionary());
|
| }
|
|
|
| - ASSERT(map()->has_dictionary_elements());
|
| - if (new_element_dictionary != NULL) {
|
| - set_elements(new_element_dictionary);
|
| + ASSERT(object->map()->has_dictionary_elements());
|
| + if (!new_element_dictionary.is_null()) {
|
| + object->set_elements(*new_element_dictionary);
|
| }
|
|
|
| - if (elements() != heap->empty_slow_element_dictionary()) {
|
| - SeededNumberDictionary* dictionary = element_dictionary();
|
| + if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
|
| + SeededNumberDictionary* dictionary = object->element_dictionary();
|
| // Make sure we never go back to the fast case
|
| dictionary->set_requires_slow_elements();
|
| // Freeze all elements in the dictionary
|
| FreezeDictionary(dictionary);
|
| }
|
|
|
| - return this;
|
| + return object;
|
| }
|
|
|
|
|
| @@ -5635,17 +5565,6 @@ MUST_USE_RESULT MaybeObject* JSObject::SetObserved(Isolate* isolate) {
|
| }
|
|
|
|
|
| -// TODO(mstarzinger): Temporary wrapper until handlified.
|
| -static Handle<Object> NewStorageFor(Isolate* isolate,
|
| - Handle<Object> object,
|
| - Representation representation) {
|
| - Heap* heap = isolate->heap();
|
| - CALL_HEAP_FUNCTION(isolate,
|
| - object->AllocateNewStorageFor(heap, representation),
|
| - Object);
|
| -}
|
| -
|
| -
|
| Handle<JSObject> JSObject::Copy(Handle<JSObject> object) {
|
| Isolate* isolate = object->GetIsolate();
|
| CALL_HEAP_FUNCTION(isolate,
|
| @@ -5667,6 +5586,8 @@ Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object) {
|
|
|
| Handle<JSObject> copy = Copy(object);
|
|
|
| + HandleScope scope(isolate);
|
| +
|
| // Deep copy local properties.
|
| if (copy->HasFastProperties()) {
|
| Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
|
| @@ -6194,7 +6115,7 @@ void JSObject::DefineAccessor(Handle<JSObject> object,
|
| bool preexists = false;
|
| if (is_observed) {
|
| if (is_element) {
|
| - preexists = object->HasLocalElement(index);
|
| + preexists = HasLocalElement(object, index);
|
| if (preexists && object->GetLocalElementAccessorPair(index) == NULL) {
|
| old_value = Object::GetElement(isolate, object, index);
|
| }
|
| @@ -6664,6 +6585,16 @@ MaybeObject* Map::ShareDescriptor(DescriptorArray* descriptors,
|
| }
|
|
|
|
|
| +Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map,
|
| + Handle<DescriptorArray> descriptors,
|
| + TransitionFlag flag,
|
| + Handle<Name> name) {
|
| + CALL_HEAP_FUNCTION(map->GetIsolate(),
|
| + map->CopyReplaceDescriptors(*descriptors, flag, *name),
|
| + Map);
|
| +}
|
| +
|
| +
|
| MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
|
| TransitionFlag flag,
|
| Name* name,
|
| @@ -6690,6 +6621,15 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
|
| }
|
|
|
|
|
| +Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map,
|
| + int new_descriptor,
|
| + Handle<DescriptorArray> 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,
|
| @@ -6908,6 +6848,16 @@ MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor,
|
| }
|
|
|
|
|
| +Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
|
| + Handle<DescriptorArray> desc,
|
| + int enumeration_index,
|
| + PropertyAttributes attributes) {
|
| + CALL_HEAP_FUNCTION(desc->GetIsolate(),
|
| + desc->CopyUpToAddAttributes(enumeration_index, attributes),
|
| + DescriptorArray);
|
| +}
|
| +
|
| +
|
| MaybeObject* DescriptorArray::CopyUpToAddAttributes(
|
| int enumeration_index, PropertyAttributes attributes) {
|
| if (enumeration_index == 0) return GetHeap()->empty_descriptor_array();
|
| @@ -7802,6 +7752,20 @@ void DescriptorArray::CopyFrom(int dst_index,
|
| }
|
|
|
|
|
| +Handle<DescriptorArray> DescriptorArray::Merge(Handle<DescriptorArray> desc,
|
| + int verbatim,
|
| + int valid,
|
| + int new_size,
|
| + int modify_index,
|
| + StoreMode store_mode,
|
| + Handle<DescriptorArray> 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
|
| @@ -9028,18 +8992,7 @@ AllocationMemento* AllocationMemento::FindForJSObject(JSObject* object) {
|
| object->GetHeap()->allocation_memento_map()) {
|
| AllocationMemento* memento = AllocationMemento::cast(
|
| reinterpret_cast<Object*>(ptr_end + kHeapObjectTag));
|
| -
|
| - // TODO(mvstanton): because of chromium bug 284577, put extra care
|
| - // into validating that the memento points to a valid AllocationSite.
|
| - // This check is expensive so remove it asap. Also, this check
|
| - // HIDES bug 284577, so it must be disabled to debug/diagnose.
|
| - Object* site = memento->allocation_site();
|
| - Heap* heap = object->GetHeap();
|
| - if (heap->InOldPointerSpace(site) &&
|
| - site->IsHeapObject() &&
|
| - HeapObject::cast(site)->map() == heap->allocation_site_map()) {
|
| - return memento;
|
| - }
|
| + return memento;
|
| }
|
| }
|
| }
|
| @@ -10424,10 +10377,9 @@ void Code::ClearTypeFeedbackCells(Heap* heap) {
|
| BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
|
| DisallowHeapAllocation no_gc;
|
| ASSERT(kind() == FUNCTION);
|
| - for (FullCodeGenerator::BackEdgeTableIterator it(this, &no_gc);
|
| - !it.Done();
|
| - it.Next()) {
|
| - if (it.pc_offset() == pc_offset) return it.ast_id();
|
| + BackEdgeTable back_edges(this, &no_gc);
|
| + for (uint32_t i = 0; i < back_edges.length(); i++) {
|
| + if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
|
| }
|
| return BailoutId::None();
|
| }
|
| @@ -10895,15 +10847,15 @@ void Code::Disassemble(const char* name, FILE* out) {
|
| // (due to alignment) the end of the instruction stream.
|
| if (static_cast<int>(offset) < instruction_size()) {
|
| DisallowHeapAllocation no_gc;
|
| - FullCodeGenerator::BackEdgeTableIterator back_edges(this, &no_gc);
|
| + BackEdgeTable back_edges(this, &no_gc);
|
|
|
| - PrintF(out, "Back edges (size = %u)\n", back_edges.table_length());
|
| + PrintF(out, "Back edges (size = %u)\n", back_edges.length());
|
| PrintF(out, "ast_id pc_offset loop_depth\n");
|
|
|
| - for ( ; !back_edges.Done(); back_edges.Next()) {
|
| - PrintF(out, "%6d %9u %10u\n", back_edges.ast_id().ToInt(),
|
| - back_edges.pc_offset(),
|
| - back_edges.loop_depth());
|
| + for (uint32_t i = 0; i < back_edges.length(); i++) {
|
| + PrintF(out, "%6d %9u %10u\n", back_edges.ast_id(i).ToInt(),
|
| + back_edges.pc_offset(i),
|
| + back_edges.loop_depth(i));
|
| }
|
|
|
| PrintF(out, "\n");
|
| @@ -10974,6 +10926,10 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength(
|
| }
|
| ValidateElements();
|
| set_map_and_elements(new_map, new_elements);
|
| +
|
| + // Transition through the allocation site as well if present.
|
| + maybe_obj = UpdateAllocationSite(new_elements_kind);
|
| + if (maybe_obj->IsFailure()) return maybe_obj;
|
| } else {
|
| FixedArray* parameter_map = FixedArray::cast(old_elements);
|
| parameter_map->set(1, new_elements);
|
| @@ -11725,18 +11681,17 @@ MaybeObject* JSObject::GetElementWithCallback(Object* receiver,
|
| }
|
|
|
|
|
| -MaybeObject* JSObject::SetElementWithCallback(Object* structure,
|
| - uint32_t index,
|
| - Object* value,
|
| - JSObject* holder,
|
| - StrictModeFlag strict_mode) {
|
| - Isolate* isolate = GetIsolate();
|
| - HandleScope scope(isolate);
|
| +Handle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object,
|
| + Handle<Object> structure,
|
| + uint32_t index,
|
| + Handle<Object> value,
|
| + Handle<JSObject> holder,
|
| + StrictModeFlag strict_mode) {
|
| + Isolate* isolate = object->GetIsolate();
|
|
|
| // We should never get here to initialize a const with the hole
|
| // value since a const declaration would conflict with the setter.
|
| ASSERT(!value->IsTheHole());
|
| - Handle<Object> value_handle(value, isolate);
|
|
|
| // To accommodate both the old and the new api we switch on the
|
| // data structure used to store the callbacks. Eventually foreign
|
| @@ -11745,41 +11700,40 @@ MaybeObject* JSObject::SetElementWithCallback(Object* structure,
|
|
|
| if (structure->IsExecutableAccessorInfo()) {
|
| // api style callbacks
|
| - Handle<JSObject> self(this);
|
| - Handle<JSObject> holder_handle(JSObject::cast(holder));
|
| - Handle<ExecutableAccessorInfo> data(
|
| - ExecutableAccessorInfo::cast(structure));
|
| + Handle<ExecutableAccessorInfo> data =
|
| + Handle<ExecutableAccessorInfo>::cast(structure);
|
| Object* call_obj = data->setter();
|
| v8::AccessorSetterCallback call_fun =
|
| v8::ToCData<v8::AccessorSetterCallback>(call_obj);
|
| if (call_fun == NULL) return value;
|
| Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
|
| Handle<String> key(isolate->factory()->NumberToString(number));
|
| - LOG(isolate, ApiNamedPropertyAccess("store", *self, *key));
|
| + LOG(isolate, ApiNamedPropertyAccess("store", *object, *key));
|
| PropertyCallbackArguments
|
| - args(isolate, data->data(), *self, *holder_handle);
|
| + args(isolate, data->data(), *object, *holder);
|
| args.Call(call_fun,
|
| v8::Utils::ToLocal(key),
|
| - v8::Utils::ToLocal(value_handle));
|
| - RETURN_IF_SCHEDULED_EXCEPTION(isolate);
|
| - return *value_handle;
|
| + v8::Utils::ToLocal(value));
|
| + RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| + return value;
|
| }
|
|
|
| if (structure->IsAccessorPair()) {
|
| - Handle<Object> setter(AccessorPair::cast(structure)->setter(), isolate);
|
| + Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
|
| if (setter->IsSpecFunction()) {
|
| // TODO(rossberg): nicer would be to cast to some JSCallable here...
|
| - return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value);
|
| + return SetPropertyWithDefinedSetter(
|
| + object, Handle<JSReceiver>::cast(setter), value);
|
| } else {
|
| if (strict_mode == kNonStrictMode) {
|
| return value;
|
| }
|
| - Handle<Object> holder_handle(holder, isolate);
|
| Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
|
| - Handle<Object> args[2] = { key, holder_handle };
|
| - return isolate->Throw(
|
| - *isolate->factory()->NewTypeError("no_setter_in_callback",
|
| - HandleVector(args, 2)));
|
| + Handle<Object> args[2] = { key, holder };
|
| + Handle<Object> error = isolate->factory()->NewTypeError(
|
| + "no_setter_in_callback", HandleVector(args, 2));
|
| + isolate->Throw(*error);
|
| + return Handle<Object>();
|
| }
|
| }
|
|
|
| @@ -11787,7 +11741,7 @@ MaybeObject* JSObject::SetElementWithCallback(Object* structure,
|
| if (structure->IsDeclaredAccessorInfo()) return value;
|
|
|
| UNREACHABLE();
|
| - return NULL;
|
| + return Handle<Object>();
|
| }
|
|
|
|
|
| @@ -11984,10 +11938,13 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
|
|
|
| int entry = dictionary->FindEntry(index);
|
| if (entry != SeededNumberDictionary::kNotFound) {
|
| - Object* element = dictionary->ValueAt(entry);
|
| + Handle<Object> element(dictionary->ValueAt(entry), isolate);
|
| PropertyDetails details = dictionary->DetailsAt(entry);
|
| if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) {
|
| - return SetElementWithCallback(element, index, *value, this, strict_mode);
|
| + Handle<Object> result = SetElementWithCallback(self, element, index,
|
| + value, self, strict_mode);
|
| + RETURN_IF_EMPTY_HANDLE(isolate, result);
|
| + return *result;
|
| } else {
|
| dictionary->UpdateMaxNumberKey(index);
|
| // If a value has not been initialized we allow writing to it even if it
|
| @@ -12012,13 +11969,13 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
|
| }
|
| // Elements of the arguments object in slow mode might be slow aliases.
|
| if (is_arguments && element->IsAliasedArgumentsEntry()) {
|
| - AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(element);
|
| + AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*element);
|
| Context* context = Context::cast(elements->get(0));
|
| int context_index = entry->aliased_context_slot();
|
| ASSERT(!context->get(context_index)->IsTheHole());
|
| context->set(context_index, *value);
|
| // For elements that are still writable we keep slow aliasing.
|
| - if (!details.IsReadOnly()) value = handle(element, isolate);
|
| + if (!details.IsReadOnly()) value = element;
|
| }
|
| dictionary->ValueAtPut(entry, *value);
|
| }
|
| @@ -12508,7 +12465,7 @@ MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) {
|
| if (IsHoleyElementsKind(kind)) {
|
| to_kind = GetHoleyElementsKind(to_kind);
|
| }
|
| - if (AllocationSite::GetMode(kind, to_kind) == TRACK_ALLOCATION_SITE) {
|
| + if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
|
| // If the array is huge, it's not likely to be defined in a local
|
| // function, so we shouldn't make new instances of it very often.
|
| uint32_t length = 0;
|
| @@ -12530,7 +12487,7 @@ MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) {
|
| if (IsHoleyElementsKind(kind)) {
|
| to_kind = GetHoleyElementsKind(to_kind);
|
| }
|
| - if (AllocationSite::GetMode(kind, to_kind) == TRACK_ALLOCATION_SITE) {
|
| + if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
|
| if (FLAG_trace_track_allocation_sites) {
|
| PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
|
| reinterpret_cast<void*>(this),
|
| @@ -14524,17 +14481,6 @@ PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) {
|
| }
|
|
|
|
|
| -// TODO(mstarzinger): Temporary wrapper until handlified.
|
| -static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - PropertyDetails details) {
|
| - CALL_HEAP_FUNCTION(dict->GetIsolate(),
|
| - dict->Add(*name, *value, details),
|
| - NameDictionary);
|
| -}
|
| -
|
| -
|
| Handle<PropertyCell> GlobalObject::EnsurePropertyCell(
|
| Handle<GlobalObject> global,
|
| Handle<Name> name) {
|
| @@ -16113,6 +16059,14 @@ Type* PropertyCell::UpdateType(Handle<PropertyCell> cell,
|
| }
|
|
|
|
|
| +void PropertyCell::SetValueInferType(Handle<PropertyCell> cell,
|
| + Handle<Object> value,
|
| + WriteBarrierMode mode) {
|
| + CALL_HEAP_FUNCTION_VOID(cell->GetIsolate(),
|
| + cell->SetValueInferType(*value, mode));
|
| +}
|
| +
|
| +
|
| MaybeObject* PropertyCell::SetValueInferType(Object* value,
|
| WriteBarrierMode ignored) {
|
| set_value(value, ignored);
|
|
|