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 |