| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <iomanip> | 5 #include <iomanip> |
| 6 #include <sstream> | 6 #include <sstream> |
| 7 | 7 |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 | 9 |
| 10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
| (...skipping 3356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3367 bool is_observed = receiver->map()->is_observed() && | 3367 bool is_observed = receiver->map()->is_observed() && |
| 3368 !it->isolate()->IsInternallyUsedPropertyName(it->name()); | 3368 !it->isolate()->IsInternallyUsedPropertyName(it->name()); |
| 3369 MaybeHandle<Object> maybe_old; | 3369 MaybeHandle<Object> maybe_old; |
| 3370 if (is_observed) maybe_old = it->GetDataValue(); | 3370 if (is_observed) maybe_old = it->GetDataValue(); |
| 3371 | 3371 |
| 3372 // Possibly migrate to the most up-to-date map that will be able to store | 3372 // Possibly migrate to the most up-to-date map that will be able to store |
| 3373 // |value| under it->name(). | 3373 // |value| under it->name(). |
| 3374 it->PrepareForDataProperty(value); | 3374 it->PrepareForDataProperty(value); |
| 3375 | 3375 |
| 3376 // Write the property value. | 3376 // Write the property value. |
| 3377 value = it->WriteDataValue(value); | 3377 it->WriteDataValue(value); |
| 3378 | 3378 |
| 3379 // Send the change record if there are observers. | 3379 // Send the change record if there are observers. |
| 3380 if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) { | 3380 if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) { |
| 3381 RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord( | 3381 RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord( |
| 3382 receiver, "update", it->name(), | 3382 receiver, "update", it->name(), |
| 3383 maybe_old.ToHandleChecked()), | 3383 maybe_old.ToHandleChecked()), |
| 3384 Object); | 3384 Object); |
| 3385 } | 3385 } |
| 3386 | 3386 |
| 3387 return value; | 3387 return value; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3422 it->ApplyTransitionToDataProperty(); | 3422 it->ApplyTransitionToDataProperty(); |
| 3423 | 3423 |
| 3424 // TODO(verwaest): Encapsulate dictionary handling better. | 3424 // TODO(verwaest): Encapsulate dictionary handling better. |
| 3425 if (receiver->map()->is_dictionary_map()) { | 3425 if (receiver->map()->is_dictionary_map()) { |
| 3426 // TODO(verwaest): Probably should ensure this is done beforehand. | 3426 // TODO(verwaest): Probably should ensure this is done beforehand. |
| 3427 it->InternalizeName(); | 3427 it->InternalizeName(); |
| 3428 // TODO(dcarney): just populate TransitionPropertyCell here? | 3428 // TODO(dcarney): just populate TransitionPropertyCell here? |
| 3429 JSObject::AddSlowProperty(receiver, it->name(), value, attributes); | 3429 JSObject::AddSlowProperty(receiver, it->name(), value, attributes); |
| 3430 } else { | 3430 } else { |
| 3431 // Write the property value. | 3431 // Write the property value. |
| 3432 value = it->WriteDataValue(value); | 3432 it->WriteDataValue(value); |
| 3433 } | 3433 } |
| 3434 | 3434 |
| 3435 // Send the change record if there are observers. | 3435 // Send the change record if there are observers. |
| 3436 if (receiver->map()->is_observed() && | 3436 if (receiver->map()->is_observed() && |
| 3437 !it->isolate()->IsInternallyUsedPropertyName(it->name())) { | 3437 !it->isolate()->IsInternallyUsedPropertyName(it->name())) { |
| 3438 RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord( | 3438 RETURN_ON_EXCEPTION(it->isolate(), JSObject::EnqueueChangeRecord( |
| 3439 receiver, "add", it->name(), | 3439 receiver, "add", it->name(), |
| 3440 it->factory()->the_hole_value()), | 3440 it->factory()->the_hole_value()), |
| 3441 Object); | 3441 Object); |
| 3442 } | 3442 } |
| (...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4286 RETURN_ON_EXCEPTION( | 4286 RETURN_ON_EXCEPTION( |
| 4287 it.isolate(), | 4287 it.isolate(), |
| 4288 EnqueueChangeRecord(object, "reconfigure", name, | 4288 EnqueueChangeRecord(object, "reconfigure", name, |
| 4289 it.isolate()->factory()->the_hole_value()), | 4289 it.isolate()->factory()->the_hole_value()), |
| 4290 Object); | 4290 Object); |
| 4291 } | 4291 } |
| 4292 return value; | 4292 return value; |
| 4293 } | 4293 } |
| 4294 | 4294 |
| 4295 it.ReconfigureDataProperty(value, attributes); | 4295 it.ReconfigureDataProperty(value, attributes); |
| 4296 value = it.WriteDataValue(value); | 4296 it.WriteDataValue(value); |
| 4297 | 4297 |
| 4298 if (is_observed) { | 4298 if (is_observed) { |
| 4299 RETURN_ON_EXCEPTION( | 4299 RETURN_ON_EXCEPTION( |
| 4300 it.isolate(), | 4300 it.isolate(), |
| 4301 EnqueueChangeRecord(object, "reconfigure", name, | 4301 EnqueueChangeRecord(object, "reconfigure", name, |
| 4302 it.isolate()->factory()->the_hole_value()), | 4302 it.isolate()->factory()->the_hole_value()), |
| 4303 Object); | 4303 Object); |
| 4304 } | 4304 } |
| 4305 | 4305 |
| 4306 return value; | 4306 return value; |
| 4307 } | 4307 } |
| 4308 | 4308 |
| 4309 case LookupIterator::DATA: { | 4309 case LookupIterator::DATA: { |
| 4310 PropertyDetails details = it.property_details(); | 4310 PropertyDetails details = it.property_details(); |
| 4311 Handle<Object> old_value = it.isolate()->factory()->the_hole_value(); | 4311 Handle<Object> old_value = it.isolate()->factory()->the_hole_value(); |
| 4312 // Regular property update if the attributes match. | 4312 // Regular property update if the attributes match. |
| 4313 if (details.attributes() == attributes) { | 4313 if (details.attributes() == attributes) { |
| 4314 return SetDataProperty(&it, value); | 4314 return SetDataProperty(&it, value); |
| 4315 } | 4315 } |
| 4316 // Reconfigure the data property if the attributes mismatch. | 4316 // Reconfigure the data property if the attributes mismatch. |
| 4317 if (is_observed) old_value = it.GetDataValue(); | 4317 if (is_observed) old_value = it.GetDataValue(); |
| 4318 | 4318 |
| 4319 it.ReconfigureDataProperty(value, attributes); | 4319 it.ReconfigureDataProperty(value, attributes); |
| 4320 value = it.WriteDataValue(value); | 4320 it.WriteDataValue(value); |
| 4321 | 4321 |
| 4322 if (is_observed) { | 4322 if (is_observed) { |
| 4323 if (old_value->SameValue(*value)) { | 4323 if (old_value->SameValue(*value)) { |
| 4324 old_value = it.isolate()->factory()->the_hole_value(); | 4324 old_value = it.isolate()->factory()->the_hole_value(); |
| 4325 } | 4325 } |
| 4326 RETURN_ON_EXCEPTION( | 4326 RETURN_ON_EXCEPTION( |
| 4327 it.isolate(), | 4327 it.isolate(), |
| 4328 EnqueueChangeRecord(object, "reconfigure", name, old_value), | 4328 EnqueueChangeRecord(object, "reconfigure", name, old_value), |
| 4329 Object); | 4329 Object); |
| 4330 } | 4330 } |
| (...skipping 12818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17149 } | 17149 } |
| 17150 // Fall through. | 17150 // Fall through. |
| 17151 case PropertyCellType::kMutable: | 17151 case PropertyCellType::kMutable: |
| 17152 return PropertyCellType::kMutable; | 17152 return PropertyCellType::kMutable; |
| 17153 } | 17153 } |
| 17154 UNREACHABLE(); | 17154 UNREACHABLE(); |
| 17155 return PropertyCellType::kMutable; | 17155 return PropertyCellType::kMutable; |
| 17156 } | 17156 } |
| 17157 | 17157 |
| 17158 | 17158 |
| 17159 Handle<Object> PropertyCell::UpdateCell(Handle<NameDictionary> dictionary, | 17159 void PropertyCell::UpdateCell(Handle<NameDictionary> dictionary, int entry, |
| 17160 int entry, Handle<Object> value, | 17160 Handle<Object> value, PropertyDetails details) { |
| 17161 PropertyDetails details) { | |
| 17162 DCHECK(!value->IsTheHole()); | 17161 DCHECK(!value->IsTheHole()); |
| 17163 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); | 17162 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); |
| 17164 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); | 17163 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
| 17165 const PropertyDetails original_details = dictionary->DetailsAt(entry); | 17164 const PropertyDetails original_details = dictionary->DetailsAt(entry); |
| 17166 // Data accesses could be cached in ics or optimized code. | 17165 // Data accesses could be cached in ics or optimized code. |
| 17167 bool invalidate = | 17166 bool invalidate = |
| 17168 original_details.kind() == kData && details.kind() == kAccessor; | 17167 original_details.kind() == kData && details.kind() == kAccessor; |
| 17169 int index = original_details.dictionary_index(); | 17168 int index = original_details.dictionary_index(); |
| 17170 auto old_type = original_details.cell_type(); | 17169 auto old_type = original_details.cell_type(); |
| 17171 // Preserve the enumeration index unless the property was deleted or never | 17170 // Preserve the enumeration index unless the property was deleted or never |
| 17172 // initialized. | 17171 // initialized. |
| 17173 if (cell->value()->IsTheHole()) { | 17172 if (cell->value()->IsTheHole()) { |
| 17174 index = dictionary->NextEnumerationIndex(); | 17173 index = dictionary->NextEnumerationIndex(); |
| 17175 dictionary->SetNextEnumerationIndex(index + 1); | 17174 dictionary->SetNextEnumerationIndex(index + 1); |
| 17176 // Negative lookup cells must be invalidated. | 17175 // Negative lookup cells must be invalidated. |
| 17177 invalidate = true; | 17176 invalidate = true; |
| 17178 } | 17177 } |
| 17179 DCHECK(index > 0); | 17178 DCHECK(index > 0); |
| 17180 details = details.set_index(index); | 17179 details = details.set_index(index); |
| 17181 | 17180 |
| 17182 // Heuristic: if a small-ish string is stored in a previously uninitialized | |
| 17183 // property cell, internalize it. | |
| 17184 const int kMaxLengthForInternalization = 200; | |
| 17185 if ((old_type == PropertyCellType::kUninitialized || | |
| 17186 old_type == PropertyCellType::kUndefined) && | |
| 17187 value->IsString()) { | |
| 17188 auto string = Handle<String>::cast(value); | |
| 17189 if (string->length() <= kMaxLengthForInternalization) { | |
| 17190 value = cell->GetIsolate()->factory()->InternalizeString(string); | |
| 17191 } | |
| 17192 } | |
| 17193 | |
| 17194 auto new_type = UpdatedType(cell, value, original_details); | 17181 auto new_type = UpdatedType(cell, value, original_details); |
| 17195 if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry); | 17182 if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry); |
| 17196 | 17183 |
| 17197 // Install new property details and cell value. | 17184 // Install new property details and cell value. |
| 17198 details = details.set_cell_type(new_type); | 17185 details = details.set_cell_type(new_type); |
| 17199 dictionary->DetailsAtPut(entry, details); | 17186 dictionary->DetailsAtPut(entry, details); |
| 17200 cell->set_value(*value); | 17187 cell->set_value(*value); |
| 17201 | 17188 |
| 17202 // Deopt when transitioning from a constant type. | 17189 // Deopt when transitioning from a constant type. |
| 17203 if (!invalidate && (old_type != new_type)) { | 17190 if (!invalidate && (old_type != new_type)) { |
| 17204 auto isolate = dictionary->GetIsolate(); | 17191 auto isolate = dictionary->GetIsolate(); |
| 17205 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17192 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 17206 isolate, DependentCode::kPropertyCellChangedGroup); | 17193 isolate, DependentCode::kPropertyCellChangedGroup); |
| 17207 } | 17194 } |
| 17208 return value; | |
| 17209 } | 17195 } |
| 17210 | 17196 |
| 17211 | 17197 |
| 17212 // static | 17198 // static |
| 17213 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell, | 17199 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell, |
| 17214 Handle<Object> new_value) { | 17200 Handle<Object> new_value) { |
| 17215 if (cell->value() != *new_value) { | 17201 if (cell->value() != *new_value) { |
| 17216 cell->set_value(*new_value); | 17202 cell->set_value(*new_value); |
| 17217 Isolate* isolate = cell->GetIsolate(); | 17203 Isolate* isolate = cell->GetIsolate(); |
| 17218 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17204 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 17219 isolate, DependentCode::kPropertyCellChangedGroup); | 17205 isolate, DependentCode::kPropertyCellChangedGroup); |
| 17220 } | 17206 } |
| 17221 } | 17207 } |
| 17222 } } // namespace v8::internal | 17208 } } // namespace v8::internal |
| OLD | NEW |