| 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 1768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1779 } | 1779 } |
| 1780 | 1780 |
| 1781 | 1781 |
| 1782 void JSObject::AddSlowProperty(Handle<JSObject> object, | 1782 void JSObject::AddSlowProperty(Handle<JSObject> object, |
| 1783 Handle<Name> name, | 1783 Handle<Name> name, |
| 1784 Handle<Object> value, | 1784 Handle<Object> value, |
| 1785 PropertyAttributes attributes) { | 1785 PropertyAttributes attributes) { |
| 1786 DCHECK(!object->HasFastProperties()); | 1786 DCHECK(!object->HasFastProperties()); |
| 1787 Isolate* isolate = object->GetIsolate(); | 1787 Isolate* isolate = object->GetIsolate(); |
| 1788 Handle<NameDictionary> dict(object->property_dictionary()); | 1788 Handle<NameDictionary> dict(object->property_dictionary()); |
| 1789 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | 1789 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kInvalid); |
| 1790 if (object->IsGlobalObject()) { | 1790 if (object->IsGlobalObject()) { |
| 1791 int entry = dict->FindEntry(name); | 1791 int entry = dict->FindEntry(name); |
| 1792 // If there's a cell there, just invalidate and set the property. | 1792 // If there's a cell there, just invalidate and set the property. |
| 1793 if (entry != NameDictionary::kNotFound) { | 1793 if (entry != NameDictionary::kNotFound) { |
| 1794 PropertyCell::UpdateCell(dict, entry, value, details); | 1794 PropertyCell::UpdateCell(dict, entry, value, details); |
| 1795 // TODO(dcarney): move this to UpdateCell. | 1795 // TODO(dcarney): move this to UpdateCell. |
| 1796 // Need to adjust the details. | 1796 // Need to adjust the details. |
| 1797 int index = dict->NextEnumerationIndex(); | 1797 int index = dict->NextEnumerationIndex(); |
| 1798 dict->SetNextEnumerationIndex(index + 1); | 1798 dict->SetNextEnumerationIndex(index + 1); |
| 1799 details = dict->DetailsAt(entry).set_index(index); | 1799 details = dict->DetailsAt(entry).set_index(index); |
| (...skipping 2785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4585 NameDictionary::New(isolate, property_count); | 4585 NameDictionary::New(isolate, property_count); |
| 4586 | 4586 |
| 4587 Handle<DescriptorArray> descs(map->instance_descriptors()); | 4587 Handle<DescriptorArray> descs(map->instance_descriptors()); |
| 4588 for (int i = 0; i < real_size; i++) { | 4588 for (int i = 0; i < real_size; i++) { |
| 4589 PropertyDetails details = descs->GetDetails(i); | 4589 PropertyDetails details = descs->GetDetails(i); |
| 4590 Handle<Name> key(descs->GetKey(i)); | 4590 Handle<Name> key(descs->GetKey(i)); |
| 4591 switch (details.type()) { | 4591 switch (details.type()) { |
| 4592 case DATA_CONSTANT: { | 4592 case DATA_CONSTANT: { |
| 4593 Handle<Object> value(descs->GetConstant(i), isolate); | 4593 Handle<Object> value(descs->GetConstant(i), isolate); |
| 4594 PropertyDetails d(details.attributes(), DATA, i + 1, | 4594 PropertyDetails d(details.attributes(), DATA, i + 1, |
| 4595 PropertyCellType::kNoCell); | 4595 PropertyCellType::kInvalid); |
| 4596 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4596 dictionary = NameDictionary::Add(dictionary, key, value, d); |
| 4597 break; | 4597 break; |
| 4598 } | 4598 } |
| 4599 case DATA: { | 4599 case DATA: { |
| 4600 FieldIndex index = FieldIndex::ForDescriptor(*map, i); | 4600 FieldIndex index = FieldIndex::ForDescriptor(*map, i); |
| 4601 Handle<Object> value; | 4601 Handle<Object> value; |
| 4602 if (object->IsUnboxedDoubleField(index)) { | 4602 if (object->IsUnboxedDoubleField(index)) { |
| 4603 double old_value = object->RawFastDoublePropertyAt(index); | 4603 double old_value = object->RawFastDoublePropertyAt(index); |
| 4604 value = isolate->factory()->NewHeapNumber(old_value); | 4604 value = isolate->factory()->NewHeapNumber(old_value); |
| 4605 } else { | 4605 } else { |
| 4606 value = handle(object->RawFastPropertyAt(index), isolate); | 4606 value = handle(object->RawFastPropertyAt(index), isolate); |
| 4607 if (details.representation().IsDouble()) { | 4607 if (details.representation().IsDouble()) { |
| 4608 DCHECK(value->IsMutableHeapNumber()); | 4608 DCHECK(value->IsMutableHeapNumber()); |
| 4609 Handle<HeapNumber> old = Handle<HeapNumber>::cast(value); | 4609 Handle<HeapNumber> old = Handle<HeapNumber>::cast(value); |
| 4610 value = isolate->factory()->NewHeapNumber(old->value()); | 4610 value = isolate->factory()->NewHeapNumber(old->value()); |
| 4611 } | 4611 } |
| 4612 } | 4612 } |
| 4613 PropertyDetails d(details.attributes(), DATA, i + 1, | 4613 PropertyDetails d(details.attributes(), DATA, i + 1, |
| 4614 PropertyCellType::kNoCell); | 4614 PropertyCellType::kInvalid); |
| 4615 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4615 dictionary = NameDictionary::Add(dictionary, key, value, d); |
| 4616 break; | 4616 break; |
| 4617 } | 4617 } |
| 4618 case ACCESSOR: { | 4618 case ACCESSOR: { |
| 4619 FieldIndex index = FieldIndex::ForDescriptor(*map, i); | 4619 FieldIndex index = FieldIndex::ForDescriptor(*map, i); |
| 4620 Handle<Object> value(object->RawFastPropertyAt(index), isolate); | 4620 Handle<Object> value(object->RawFastPropertyAt(index), isolate); |
| 4621 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, | 4621 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, |
| 4622 PropertyCellType::kNoCell); | 4622 PropertyCellType::kInvalid); |
| 4623 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4623 dictionary = NameDictionary::Add(dictionary, key, value, d); |
| 4624 break; | 4624 break; |
| 4625 } | 4625 } |
| 4626 case ACCESSOR_CONSTANT: { | 4626 case ACCESSOR_CONSTANT: { |
| 4627 Handle<Object> value(descs->GetCallbacksObject(i), isolate); | 4627 Handle<Object> value(descs->GetCallbacksObject(i), isolate); |
| 4628 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, | 4628 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, |
| 4629 PropertyCellType::kNoCell); | 4629 PropertyCellType::kInvalid); |
| 4630 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4630 dictionary = NameDictionary::Add(dictionary, key, value, d); |
| 4631 break; | 4631 break; |
| 4632 } | 4632 } |
| 4633 } | 4633 } |
| 4634 } | 4634 } |
| 4635 | 4635 |
| 4636 // Copy the next enumeration index from instance descriptor. | 4636 // Copy the next enumeration index from instance descriptor. |
| 4637 dictionary->SetNextEnumerationIndex(real_size + 1); | 4637 dictionary->SetNextEnumerationIndex(real_size + 1); |
| 4638 | 4638 |
| 4639 // From here on we cannot fail and we shouldn't GC anymore. | 4639 // From here on we cannot fail and we shouldn't GC anymore. |
| (...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5344 Handle<NameDictionary> dictionary(object->property_dictionary()); | 5344 Handle<NameDictionary> dictionary(object->property_dictionary()); |
| 5345 int entry = dictionary->FindEntry(name); | 5345 int entry = dictionary->FindEntry(name); |
| 5346 DCHECK_NE(NameDictionary::kNotFound, entry); | 5346 DCHECK_NE(NameDictionary::kNotFound, entry); |
| 5347 | 5347 |
| 5348 // If we have a global object, invalidate the cell and swap in a new one. | 5348 // If we have a global object, invalidate the cell and swap in a new one. |
| 5349 if (object->IsGlobalObject()) { | 5349 if (object->IsGlobalObject()) { |
| 5350 auto cell = PropertyCell::InvalidateEntry(dictionary, entry); | 5350 auto cell = PropertyCell::InvalidateEntry(dictionary, entry); |
| 5351 cell->set_value(isolate->heap()->the_hole_value()); | 5351 cell->set_value(isolate->heap()->the_hole_value()); |
| 5352 // TODO(dcarney): InvalidateForDelete | 5352 // TODO(dcarney): InvalidateForDelete |
| 5353 dictionary->DetailsAtPut(entry, dictionary->DetailsAt(entry).set_cell_type( | 5353 dictionary->DetailsAtPut(entry, dictionary->DetailsAt(entry).set_cell_type( |
| 5354 PropertyCellType::kInvalidated)); | 5354 PropertyCellType::kDeleted)); |
| 5355 return; | 5355 return; |
| 5356 } | 5356 } |
| 5357 | 5357 |
| 5358 NameDictionary::DeleteProperty(dictionary, entry); | 5358 NameDictionary::DeleteProperty(dictionary, entry); |
| 5359 Handle<NameDictionary> new_properties = | 5359 Handle<NameDictionary> new_properties = |
| 5360 NameDictionary::Shrink(dictionary, name); | 5360 NameDictionary::Shrink(dictionary, name); |
| 5361 object->set_properties(*new_properties); | 5361 object->set_properties(*new_properties); |
| 5362 } | 5362 } |
| 5363 | 5363 |
| 5364 | 5364 |
| (...skipping 1053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6418 PropertyAttributes attributes) { | 6418 PropertyAttributes attributes) { |
| 6419 int entry = dictionary->FindEntry(index); | 6419 int entry = dictionary->FindEntry(index); |
| 6420 if (entry != SeededNumberDictionary::kNotFound) { | 6420 if (entry != SeededNumberDictionary::kNotFound) { |
| 6421 Object* result = dictionary->ValueAt(entry); | 6421 Object* result = dictionary->ValueAt(entry); |
| 6422 PropertyDetails details = dictionary->DetailsAt(entry); | 6422 PropertyDetails details = dictionary->DetailsAt(entry); |
| 6423 if (details.type() == ACCESSOR_CONSTANT && result->IsAccessorPair()) { | 6423 if (details.type() == ACCESSOR_CONSTANT && result->IsAccessorPair()) { |
| 6424 DCHECK(details.IsConfigurable()); | 6424 DCHECK(details.IsConfigurable()); |
| 6425 if (details.attributes() != attributes) { | 6425 if (details.attributes() != attributes) { |
| 6426 dictionary->DetailsAtPut( | 6426 dictionary->DetailsAtPut( |
| 6427 entry, PropertyDetails(attributes, ACCESSOR_CONSTANT, index, | 6427 entry, PropertyDetails(attributes, ACCESSOR_CONSTANT, index, |
| 6428 PropertyCellType::kNoCell)); | 6428 PropertyCellType::kInvalid)); |
| 6429 } | 6429 } |
| 6430 AccessorPair::cast(result)->SetComponents(getter, setter); | 6430 AccessorPair::cast(result)->SetComponents(getter, setter); |
| 6431 return true; | 6431 return true; |
| 6432 } | 6432 } |
| 6433 } | 6433 } |
| 6434 return false; | 6434 return false; |
| 6435 } | 6435 } |
| 6436 | 6436 |
| 6437 | 6437 |
| 6438 void JSObject::DefineElementAccessor(Handle<JSObject> object, | 6438 void JSObject::DefineElementAccessor(Handle<JSObject> object, |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6521 return false; | 6521 return false; |
| 6522 } | 6522 } |
| 6523 | 6523 |
| 6524 | 6524 |
| 6525 void JSObject::SetElementCallback(Handle<JSObject> object, | 6525 void JSObject::SetElementCallback(Handle<JSObject> object, |
| 6526 uint32_t index, | 6526 uint32_t index, |
| 6527 Handle<Object> structure, | 6527 Handle<Object> structure, |
| 6528 PropertyAttributes attributes) { | 6528 PropertyAttributes attributes) { |
| 6529 Heap* heap = object->GetHeap(); | 6529 Heap* heap = object->GetHeap(); |
| 6530 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0, | 6530 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0, |
| 6531 PropertyCellType::kNoCell); | 6531 PropertyCellType::kInvalid); |
| 6532 | 6532 |
| 6533 // Normalize elements to make this operation simple. | 6533 // Normalize elements to make this operation simple. |
| 6534 bool had_dictionary_elements = object->HasDictionaryElements(); | 6534 bool had_dictionary_elements = object->HasDictionaryElements(); |
| 6535 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 6535 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
| 6536 DCHECK(object->HasDictionaryElements() || | 6536 DCHECK(object->HasDictionaryElements() || |
| 6537 object->HasDictionaryArgumentsElements()); | 6537 object->HasDictionaryArgumentsElements()); |
| 6538 // Update the dictionary with the new ACCESSOR_CONSTANT property. | 6538 // Update the dictionary with the new ACCESSOR_CONSTANT property. |
| 6539 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, | 6539 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, |
| 6540 details); | 6540 details); |
| 6541 dictionary->set_requires_slow_elements(); | 6541 dictionary->set_requires_slow_elements(); |
| (...skipping 6342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12884 // is read-only (a declared const that has not been initialized). | 12884 // is read-only (a declared const that has not been initialized). |
| 12885 return WriteToReadOnlyProperty( | 12885 return WriteToReadOnlyProperty( |
| 12886 isolate, object, isolate->factory()->NewNumberFromUint(index), | 12886 isolate, object, isolate->factory()->NewNumberFromUint(index), |
| 12887 isolate->factory()->undefined_value(), language_mode); | 12887 isolate->factory()->undefined_value(), language_mode); |
| 12888 } else { | 12888 } else { |
| 12889 DCHECK(details.IsConfigurable() || !details.IsReadOnly() || | 12889 DCHECK(details.IsConfigurable() || !details.IsReadOnly() || |
| 12890 element->IsTheHole()); | 12890 element->IsTheHole()); |
| 12891 dictionary->UpdateMaxNumberKey(index); | 12891 dictionary->UpdateMaxNumberKey(index); |
| 12892 if (set_mode == DEFINE_PROPERTY) { | 12892 if (set_mode == DEFINE_PROPERTY) { |
| 12893 details = PropertyDetails(attributes, DATA, details.dictionary_index(), | 12893 details = PropertyDetails(attributes, DATA, details.dictionary_index(), |
| 12894 PropertyCellType::kNoCell); | 12894 PropertyCellType::kInvalid); |
| 12895 dictionary->DetailsAtPut(entry, details); | 12895 dictionary->DetailsAtPut(entry, details); |
| 12896 } | 12896 } |
| 12897 | 12897 |
| 12898 // Elements of the arguments object in slow mode might be slow aliases. | 12898 // Elements of the arguments object in slow mode might be slow aliases. |
| 12899 if (is_arguments && element->IsAliasedArgumentsEntry()) { | 12899 if (is_arguments && element->IsAliasedArgumentsEntry()) { |
| 12900 Handle<AliasedArgumentsEntry> entry = | 12900 Handle<AliasedArgumentsEntry> entry = |
| 12901 Handle<AliasedArgumentsEntry>::cast(element); | 12901 Handle<AliasedArgumentsEntry>::cast(element); |
| 12902 Handle<Context> context(Context::cast(elements->get(0))); | 12902 Handle<Context> context(Context::cast(elements->get(0))); |
| 12903 int context_index = entry->aliased_context_slot(); | 12903 int context_index = entry->aliased_context_slot(); |
| 12904 DCHECK(!context->get(context_index)->IsTheHole()); | 12904 DCHECK(!context->get(context_index)->IsTheHole()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 12927 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12927 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 12928 Handle<String> name = isolate->factory()->NumberToString(number); | 12928 Handle<String> name = isolate->factory()->NumberToString(number); |
| 12929 Handle<Object> args[] = {name}; | 12929 Handle<Object> args[] = {name}; |
| 12930 THROW_NEW_ERROR(isolate, | 12930 THROW_NEW_ERROR(isolate, |
| 12931 NewTypeError("object_not_extensible", | 12931 NewTypeError("object_not_extensible", |
| 12932 HandleVector(args, arraysize(args))), | 12932 HandleVector(args, arraysize(args))), |
| 12933 Object); | 12933 Object); |
| 12934 } | 12934 } |
| 12935 } | 12935 } |
| 12936 | 12936 |
| 12937 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | 12937 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kInvalid); |
| 12938 Handle<SeededNumberDictionary> new_dictionary = | 12938 Handle<SeededNumberDictionary> new_dictionary = |
| 12939 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, | 12939 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, |
| 12940 details); | 12940 details); |
| 12941 if (*dictionary != *new_dictionary) { | 12941 if (*dictionary != *new_dictionary) { |
| 12942 if (is_arguments) { | 12942 if (is_arguments) { |
| 12943 elements->set(1, *new_dictionary); | 12943 elements->set(1, *new_dictionary); |
| 12944 } else { | 12944 } else { |
| 12945 object->set_elements(*new_dictionary); | 12945 object->set_elements(*new_dictionary); |
| 12946 } | 12946 } |
| 12947 dictionary = new_dictionary; | 12947 dictionary = new_dictionary; |
| (...skipping 2411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15359 Handle<GlobalObject> global, Handle<Name> name) { | 15359 Handle<GlobalObject> global, Handle<Name> name) { |
| 15360 DCHECK(!global->HasFastProperties()); | 15360 DCHECK(!global->HasFastProperties()); |
| 15361 auto dictionary = handle(global->property_dictionary()); | 15361 auto dictionary = handle(global->property_dictionary()); |
| 15362 int entry = dictionary->FindEntry(name); | 15362 int entry = dictionary->FindEntry(name); |
| 15363 Handle<PropertyCell> cell; | 15363 Handle<PropertyCell> cell; |
| 15364 if (entry != NameDictionary::kNotFound) { | 15364 if (entry != NameDictionary::kNotFound) { |
| 15365 // This call should be idempotent. | 15365 // This call should be idempotent. |
| 15366 DCHECK(dictionary->DetailsAt(entry).cell_type() == | 15366 DCHECK(dictionary->DetailsAt(entry).cell_type() == |
| 15367 PropertyCellType::kUninitialized || | 15367 PropertyCellType::kUninitialized || |
| 15368 dictionary->DetailsAt(entry).cell_type() == | 15368 dictionary->DetailsAt(entry).cell_type() == |
| 15369 PropertyCellType::kInvalidated); | 15369 PropertyCellType::kDeleted); |
| 15370 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); | 15370 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); |
| 15371 cell = handle(PropertyCell::cast(dictionary->ValueAt(entry))); | 15371 cell = handle(PropertyCell::cast(dictionary->ValueAt(entry))); |
| 15372 DCHECK(cell->value()->IsTheHole()); | 15372 DCHECK(cell->value()->IsTheHole()); |
| 15373 return cell; | 15373 return cell; |
| 15374 } | 15374 } |
| 15375 Isolate* isolate = global->GetIsolate(); | 15375 Isolate* isolate = global->GetIsolate(); |
| 15376 cell = isolate->factory()->NewPropertyCell(); | 15376 cell = isolate->factory()->NewPropertyCell(); |
| 15377 PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized); | 15377 PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized); |
| 15378 dictionary = NameDictionary::Add(dictionary, name, cell, details); | 15378 dictionary = NameDictionary::Add(dictionary, name, cell, details); |
| 15379 global->set_properties(*dictionary); | 15379 global->set_properties(*dictionary); |
| (...skipping 1614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16994 Isolate* isolate = dictionary->GetIsolate(); | 16994 Isolate* isolate = dictionary->GetIsolate(); |
| 16995 // Swap with a copy. | 16995 // Swap with a copy. |
| 16996 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); | 16996 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); |
| 16997 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); | 16997 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
| 16998 auto new_cell = isolate->factory()->NewPropertyCell(); | 16998 auto new_cell = isolate->factory()->NewPropertyCell(); |
| 16999 new_cell->set_value(cell->value()); | 16999 new_cell->set_value(cell->value()); |
| 17000 dictionary->ValueAtPut(entry, *new_cell); | 17000 dictionary->ValueAtPut(entry, *new_cell); |
| 17001 bool is_the_hole = cell->value()->IsTheHole(); | 17001 bool is_the_hole = cell->value()->IsTheHole(); |
| 17002 // Cell is officially mutable henceforth. | 17002 // Cell is officially mutable henceforth. |
| 17003 auto details = dictionary->DetailsAt(entry); | 17003 auto details = dictionary->DetailsAt(entry); |
| 17004 details = details.set_cell_type(is_the_hole ? PropertyCellType::kInvalidated | 17004 details = details.set_cell_type(is_the_hole ? PropertyCellType::kDeleted |
| 17005 : PropertyCellType::kMutable); | 17005 : PropertyCellType::kMutable); |
| 17006 dictionary->DetailsAtPut(entry, details); | 17006 dictionary->DetailsAtPut(entry, details); |
| 17007 // Old cell is ready for invalidation. | 17007 // Old cell is ready for invalidation. |
| 17008 if (is_the_hole) { | 17008 if (is_the_hole) { |
| 17009 cell->set_value(isolate->heap()->undefined_value()); | 17009 cell->set_value(isolate->heap()->undefined_value()); |
| 17010 } else { | 17010 } else { |
| 17011 cell->set_value(isolate->heap()->the_hole_value()); | 17011 cell->set_value(isolate->heap()->the_hole_value()); |
| 17012 } | 17012 } |
| 17013 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17013 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 17014 isolate, DependentCode::kPropertyCellChangedGroup); | 17014 isolate, DependentCode::kPropertyCellChangedGroup); |
| 17015 return new_cell; | 17015 return new_cell; |
| 17016 } | 17016 } |
| 17017 | 17017 |
| 17018 | 17018 |
| 17019 PropertyCellConstantType PropertyCell::GetConstantType() { | |
| 17020 if (value()->IsSmi()) return PropertyCellConstantType::kSmi; | |
| 17021 return PropertyCellConstantType::kStableMap; | |
| 17022 } | |
| 17023 | |
| 17024 | |
| 17025 static bool RemainsConstantType(Handle<PropertyCell> cell, | |
| 17026 Handle<Object> value) { | |
| 17027 // TODO(dcarney): double->smi and smi->double transition from kConstant | |
| 17028 if (cell->value()->IsSmi() && value->IsSmi()) { | |
| 17029 return true; | |
| 17030 } else if (cell->value()->IsHeapObject() && value->IsHeapObject()) { | |
| 17031 return HeapObject::cast(cell->value())->map() == | |
| 17032 HeapObject::cast(*value)->map() && | |
| 17033 HeapObject::cast(*value)->map()->is_stable(); | |
| 17034 } | |
| 17035 return false; | |
| 17036 } | |
| 17037 | |
| 17038 | |
| 17039 PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell, | 17019 PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell, |
| 17040 Handle<Object> value, | 17020 Handle<Object> value, |
| 17041 PropertyDetails details) { | 17021 PropertyDetails details) { |
| 17042 PropertyCellType type = details.cell_type(); | 17022 PropertyCellType type = details.cell_type(); |
| 17043 DCHECK(!value->IsTheHole()); | 17023 DCHECK(!value->IsTheHole()); |
| 17044 if (cell->value()->IsTheHole()) { | 17024 DCHECK_IMPLIES(cell->value()->IsTheHole(), |
| 17045 switch (type) { | 17025 type == PropertyCellType::kUninitialized || |
| 17046 // Only allow a cell to transition once into constant state. | 17026 type == PropertyCellType::kDeleted); |
| 17047 case PropertyCellType::kUninitialized: | |
| 17048 if (value->IsUndefined()) return PropertyCellType::kUndefined; | |
| 17049 return PropertyCellType::kConstant; | |
| 17050 case PropertyCellType::kInvalidated: | |
| 17051 return PropertyCellType::kMutable; | |
| 17052 default: | |
| 17053 UNREACHABLE(); | |
| 17054 return PropertyCellType::kMutable; | |
| 17055 } | |
| 17056 } | |
| 17057 switch (type) { | 17027 switch (type) { |
| 17028 // Only allow a cell to transition once into constant state. |
| 17029 case PropertyCellType::kUninitialized: |
| 17030 if (value->IsUndefined()) return PropertyCellType::kUndefined; |
| 17031 return PropertyCellType::kConstant; |
| 17058 case PropertyCellType::kUndefined: | 17032 case PropertyCellType::kUndefined: |
| 17059 return PropertyCellType::kConstant; | 17033 return PropertyCellType::kConstant; |
| 17060 case PropertyCellType::kConstant: | 17034 case PropertyCellType::kConstant: |
| 17035 // No transition. |
| 17061 if (*value == cell->value()) return PropertyCellType::kConstant; | 17036 if (*value == cell->value()) return PropertyCellType::kConstant; |
| 17062 // Fall through. | 17037 // Fall through. |
| 17063 case PropertyCellType::kConstantType: | |
| 17064 if (RemainsConstantType(cell, value)) { | |
| 17065 return PropertyCellType::kConstantType; | |
| 17066 } | |
| 17067 // Fall through. | |
| 17068 case PropertyCellType::kMutable: | 17038 case PropertyCellType::kMutable: |
| 17069 return PropertyCellType::kMutable; | 17039 return PropertyCellType::kMutable; |
| 17070 } | 17040 } |
| 17071 UNREACHABLE(); | 17041 UNREACHABLE(); |
| 17072 return PropertyCellType::kMutable; | 17042 return PropertyCellType::kMutable; |
| 17073 } | 17043 } |
| 17074 | 17044 |
| 17075 | 17045 |
| 17076 Handle<Object> PropertyCell::UpdateCell(Handle<NameDictionary> dictionary, | 17046 Handle<Object> PropertyCell::UpdateCell(Handle<NameDictionary> dictionary, |
| 17077 int entry, Handle<Object> value, | 17047 int entry, Handle<Object> value, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17110 | 17080 |
| 17111 auto new_type = UpdatedType(cell, value, original_details); | 17081 auto new_type = UpdatedType(cell, value, original_details); |
| 17112 if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry); | 17082 if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry); |
| 17113 | 17083 |
| 17114 // Install new property details and cell value. | 17084 // Install new property details and cell value. |
| 17115 details = details.set_cell_type(new_type); | 17085 details = details.set_cell_type(new_type); |
| 17116 dictionary->DetailsAtPut(entry, details); | 17086 dictionary->DetailsAtPut(entry, details); |
| 17117 cell->set_value(*value); | 17087 cell->set_value(*value); |
| 17118 | 17088 |
| 17119 // Deopt when transitioning from a constant type. | 17089 // Deopt when transitioning from a constant type. |
| 17120 if (!invalidate && (old_type != new_type)) { | 17090 if (!invalidate && old_type == PropertyCellType::kConstant && |
| 17091 new_type != PropertyCellType::kConstant) { |
| 17121 auto isolate = dictionary->GetIsolate(); | 17092 auto isolate = dictionary->GetIsolate(); |
| 17122 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17093 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 17123 isolate, DependentCode::kPropertyCellChangedGroup); | 17094 isolate, DependentCode::kPropertyCellChangedGroup); |
| 17124 } | 17095 } |
| 17125 return value; | 17096 return value; |
| 17126 } | 17097 } |
| 17127 | 17098 |
| 17128 } } // namespace v8::internal | 17099 } } // namespace v8::internal |
| OLD | NEW |