| Index: src/lookup.cc
|
| diff --git a/src/lookup.cc b/src/lookup.cc
|
| index 8e545f747904be31b389eb1c8f11e5b161b8f545..544b164a8b7064d8769f4ade67bc567705cc01c2 100644
|
| --- a/src/lookup.cc
|
| +++ b/src/lookup.cc
|
| @@ -220,6 +220,16 @@ void LookupIterator::PrepareForDataProperty(Handle<Object> value) {
|
| return;
|
| }
|
|
|
| + if (holder->IsJSGlobalObject()) {
|
| + Handle<GlobalDictionary> dictionary(holder->global_dictionary());
|
| + Handle<PropertyCell> cell(
|
| + PropertyCell::cast(dictionary->ValueAt(dictionary_entry())));
|
| + DCHECK(!cell->IsTheHole(isolate_));
|
| + property_details_ = cell->property_details();
|
| + PropertyCell::PrepareForValue(dictionary, dictionary_entry(), value,
|
| + property_details_);
|
| + return;
|
| + }
|
| if (!holder->HasFastProperties()) return;
|
|
|
| Handle<Map> old_map(holder->map(), isolate_);
|
| @@ -252,20 +262,34 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value,
|
| holder->GetElementsAccessor()->Reconfigure(holder, elements, number_, value,
|
| attributes);
|
| ReloadPropertyInformation<true>();
|
| + } else if (holder->HasFastProperties()) {
|
| + Handle<Map> old_map(holder->map(), isolate_);
|
| + Handle<Map> new_map = Map::ReconfigureExistingProperty(
|
| + old_map, descriptor_number(), i::kData, attributes);
|
| + new_map = Map::PrepareForDataProperty(new_map, descriptor_number(), value);
|
| + JSObject::MigrateToMap(holder, new_map);
|
| + ReloadPropertyInformation<false>();
|
| } else {
|
| - if (!holder->HasFastProperties()) {
|
| - PropertyDetails details(attributes, v8::internal::DATA, 0,
|
| - PropertyCellType::kMutable);
|
| - JSObject::SetNormalizedProperty(holder, name(), value, details);
|
| + PropertyDetails details(attributes, v8::internal::DATA, 0,
|
| + PropertyCellType::kMutable);
|
| + if (holder->IsJSGlobalObject()) {
|
| + Handle<GlobalDictionary> dictionary(holder->global_dictionary());
|
| +
|
| + Handle<PropertyCell> cell = PropertyCell::PrepareForValue(
|
| + dictionary, dictionary_entry(), value, details);
|
| + cell->set_value(*value);
|
| + property_details_ = cell->property_details();
|
| } else {
|
| - Handle<Map> old_map(holder->map(), isolate_);
|
| - Handle<Map> new_map = Map::ReconfigureExistingProperty(
|
| - old_map, descriptor_number(), i::kData, attributes);
|
| - new_map =
|
| - Map::PrepareForDataProperty(new_map, descriptor_number(), value);
|
| - JSObject::MigrateToMap(holder, new_map);
|
| + Handle<NameDictionary> dictionary(holder->property_dictionary());
|
| + PropertyDetails original_details =
|
| + dictionary->DetailsAt(dictionary_entry());
|
| + int enumeration_index = original_details.dictionary_index();
|
| + DCHECK(enumeration_index > 0);
|
| + details = details.set_index(enumeration_index);
|
| + dictionary->SetEntry(dictionary_entry(), name(), value, details);
|
| + property_details_ = details;
|
| }
|
| - ReloadPropertyInformation<false>();
|
| + state_ = DATA;
|
| }
|
|
|
| WriteDataValue(value);
|
| @@ -297,11 +321,31 @@ void LookupIterator::PrepareTransitionToDataProperty(
|
| state_ = TRANSITION;
|
| if (map->IsJSGlobalObjectMap()) {
|
| // Install a property cell.
|
| - auto cell = JSGlobalObject::EnsurePropertyCell(
|
| - Handle<JSGlobalObject>::cast(receiver), name());
|
| + Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(receiver);
|
| + int entry;
|
| + Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
|
| + global, name(), PropertyCellType::kUninitialized, &entry);
|
| + Handle<GlobalDictionary> dictionary(global->global_dictionary(),
|
| + isolate_);
|
| DCHECK(cell->value()->IsTheHole(isolate_));
|
| + DCHECK(!value->IsTheHole(isolate_));
|
| transition_ = cell;
|
| + // Assign an enumeration index to the property and update
|
| + // SetNextEnumerationIndex.
|
| + int index = dictionary->NextEnumerationIndex();
|
| + dictionary->SetNextEnumerationIndex(index + 1);
|
| + property_details_ = PropertyDetails(attributes, i::DATA, index,
|
| + PropertyCellType::kUninitialized);
|
| + PropertyCellType new_type =
|
| + PropertyCell::UpdatedType(cell, value, property_details_);
|
| + property_details_ = property_details_.set_cell_type(new_type);
|
| + cell->set_property_details(property_details_);
|
| + number_ = entry;
|
| + has_property_ = true;
|
| } else {
|
| + // Don't set enumeration index (it will be set during value store).
|
| + property_details_ =
|
| + PropertyDetails(attributes, i::DATA, 0, PropertyCellType::kNoCell);
|
| transition_ = map;
|
| }
|
| return;
|
| @@ -322,9 +366,11 @@ void LookupIterator::ApplyTransitionToDataProperty(Handle<JSObject> receiver) {
|
| DCHECK_EQ(TRANSITION, state_);
|
|
|
| DCHECK(receiver.is_identical_to(GetStoreTarget()));
|
| -
|
| - if (receiver->IsJSGlobalObject()) return;
|
| holder_ = receiver;
|
| + if (receiver->IsJSGlobalObject()) {
|
| + state_ = DATA;
|
| + return;
|
| + }
|
| Handle<Map> transition = transition_map();
|
| bool simple_transition = transition->GetBackPointer() == receiver->map();
|
| JSObject::MigrateToMap(receiver, transition);
|
| @@ -334,6 +380,20 @@ void LookupIterator::ApplyTransitionToDataProperty(Handle<JSObject> receiver) {
|
| number_ = static_cast<uint32_t>(number);
|
| property_details_ = transition->GetLastDescriptorDetails();
|
| state_ = DATA;
|
| + } else if (receiver->map()->is_dictionary_map()) {
|
| + Handle<NameDictionary> dictionary(receiver->property_dictionary(),
|
| + isolate_);
|
| + int entry;
|
| + dictionary = NameDictionary::Add(dictionary, name(),
|
| + isolate_->factory()->uninitialized_value(),
|
| + property_details_, &entry);
|
| + receiver->set_properties(*dictionary);
|
| + // Reload details containing proper enumeration index value.
|
| + property_details_ = dictionary->DetailsAt(entry);
|
| + number_ = entry;
|
| + has_property_ = true;
|
| + state_ = DATA;
|
| +
|
| } else {
|
| ReloadPropertyInformation<false>();
|
| }
|
| @@ -572,11 +632,10 @@ Handle<FieldType> LookupIterator::GetFieldType() const {
|
|
|
| Handle<PropertyCell> LookupIterator::GetPropertyCell() const {
|
| DCHECK(!IsElement());
|
| - Handle<JSObject> holder = GetHolder<JSObject>();
|
| - Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(holder);
|
| - Object* value = global->global_dictionary()->ValueAt(dictionary_entry());
|
| + Handle<JSGlobalObject> holder = GetHolder<JSGlobalObject>();
|
| + Object* value = holder->global_dictionary()->ValueAt(dictionary_entry());
|
| DCHECK(value->IsPropertyCell());
|
| - return handle(PropertyCell::cast(value));
|
| + return handle(PropertyCell::cast(value), isolate_);
|
| }
|
|
|
|
|
| @@ -608,13 +667,13 @@ void LookupIterator::WriteDataValue(Handle<Object> value) {
|
| DCHECK_EQ(v8::internal::DATA_CONSTANT, property_details_.type());
|
| }
|
| } else if (holder->IsJSGlobalObject()) {
|
| - Handle<GlobalDictionary> property_dictionary =
|
| - handle(JSObject::cast(*holder)->global_dictionary());
|
| - PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value,
|
| - property_details_);
|
| + GlobalDictionary* dictionary = JSObject::cast(*holder)->global_dictionary();
|
| + Object* cell = dictionary->ValueAt(dictionary_entry());
|
| + DCHECK(cell->IsPropertyCell());
|
| + PropertyCell::cast(cell)->set_value(*value);
|
| } else {
|
| - NameDictionary* property_dictionary = holder->property_dictionary();
|
| - property_dictionary->ValueAtPut(dictionary_entry(), *value);
|
| + NameDictionary* dictionary = holder->property_dictionary();
|
| + dictionary->ValueAtPut(dictionary_entry(), *value);
|
| }
|
| }
|
|
|
|
|