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 |