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::kInvalid); | 1789 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
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 2787 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4587 NameDictionary::New(isolate, property_count); | 4587 NameDictionary::New(isolate, property_count); |
4588 | 4588 |
4589 Handle<DescriptorArray> descs(map->instance_descriptors()); | 4589 Handle<DescriptorArray> descs(map->instance_descriptors()); |
4590 for (int i = 0; i < real_size; i++) { | 4590 for (int i = 0; i < real_size; i++) { |
4591 PropertyDetails details = descs->GetDetails(i); | 4591 PropertyDetails details = descs->GetDetails(i); |
4592 Handle<Name> key(descs->GetKey(i)); | 4592 Handle<Name> key(descs->GetKey(i)); |
4593 switch (details.type()) { | 4593 switch (details.type()) { |
4594 case DATA_CONSTANT: { | 4594 case DATA_CONSTANT: { |
4595 Handle<Object> value(descs->GetConstant(i), isolate); | 4595 Handle<Object> value(descs->GetConstant(i), isolate); |
4596 PropertyDetails d(details.attributes(), DATA, i + 1, | 4596 PropertyDetails d(details.attributes(), DATA, i + 1, |
4597 PropertyCellType::kInvalid); | 4597 PropertyCellType::kNoCell); |
4598 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4598 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4599 break; | 4599 break; |
4600 } | 4600 } |
4601 case DATA: { | 4601 case DATA: { |
4602 FieldIndex index = FieldIndex::ForDescriptor(*map, i); | 4602 FieldIndex index = FieldIndex::ForDescriptor(*map, i); |
4603 Handle<Object> value; | 4603 Handle<Object> value; |
4604 if (object->IsUnboxedDoubleField(index)) { | 4604 if (object->IsUnboxedDoubleField(index)) { |
4605 double old_value = object->RawFastDoublePropertyAt(index); | 4605 double old_value = object->RawFastDoublePropertyAt(index); |
4606 value = isolate->factory()->NewHeapNumber(old_value); | 4606 value = isolate->factory()->NewHeapNumber(old_value); |
4607 } else { | 4607 } else { |
4608 value = handle(object->RawFastPropertyAt(index), isolate); | 4608 value = handle(object->RawFastPropertyAt(index), isolate); |
4609 if (details.representation().IsDouble()) { | 4609 if (details.representation().IsDouble()) { |
4610 DCHECK(value->IsMutableHeapNumber()); | 4610 DCHECK(value->IsMutableHeapNumber()); |
4611 Handle<HeapNumber> old = Handle<HeapNumber>::cast(value); | 4611 Handle<HeapNumber> old = Handle<HeapNumber>::cast(value); |
4612 value = isolate->factory()->NewHeapNumber(old->value()); | 4612 value = isolate->factory()->NewHeapNumber(old->value()); |
4613 } | 4613 } |
4614 } | 4614 } |
4615 PropertyDetails d(details.attributes(), DATA, i + 1, | 4615 PropertyDetails d(details.attributes(), DATA, i + 1, |
4616 PropertyCellType::kInvalid); | 4616 PropertyCellType::kNoCell); |
4617 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4617 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4618 break; | 4618 break; |
4619 } | 4619 } |
4620 case ACCESSOR: { | 4620 case ACCESSOR: { |
4621 FieldIndex index = FieldIndex::ForDescriptor(*map, i); | 4621 FieldIndex index = FieldIndex::ForDescriptor(*map, i); |
4622 Handle<Object> value(object->RawFastPropertyAt(index), isolate); | 4622 Handle<Object> value(object->RawFastPropertyAt(index), isolate); |
4623 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, | 4623 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, |
4624 PropertyCellType::kInvalid); | 4624 PropertyCellType::kNoCell); |
4625 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4625 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4626 break; | 4626 break; |
4627 } | 4627 } |
4628 case ACCESSOR_CONSTANT: { | 4628 case ACCESSOR_CONSTANT: { |
4629 Handle<Object> value(descs->GetCallbacksObject(i), isolate); | 4629 Handle<Object> value(descs->GetCallbacksObject(i), isolate); |
4630 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, | 4630 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, |
4631 PropertyCellType::kInvalid); | 4631 PropertyCellType::kNoCell); |
4632 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4632 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4633 break; | 4633 break; |
4634 } | 4634 } |
4635 } | 4635 } |
4636 } | 4636 } |
4637 | 4637 |
4638 // Copy the next enumeration index from instance descriptor. | 4638 // Copy the next enumeration index from instance descriptor. |
4639 dictionary->SetNextEnumerationIndex(real_size + 1); | 4639 dictionary->SetNextEnumerationIndex(real_size + 1); |
4640 | 4640 |
4641 // From here on we cannot fail and we shouldn't GC anymore. | 4641 // From here on we cannot fail and we shouldn't GC anymore. |
(...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5351 Handle<NameDictionary> dictionary(object->property_dictionary()); | 5351 Handle<NameDictionary> dictionary(object->property_dictionary()); |
5352 int entry = dictionary->FindEntry(name); | 5352 int entry = dictionary->FindEntry(name); |
5353 DCHECK_NE(NameDictionary::kNotFound, entry); | 5353 DCHECK_NE(NameDictionary::kNotFound, entry); |
5354 | 5354 |
5355 // If we have a global object, invalidate the cell and swap in a new one. | 5355 // If we have a global object, invalidate the cell and swap in a new one. |
5356 if (object->IsGlobalObject()) { | 5356 if (object->IsGlobalObject()) { |
5357 auto cell = PropertyCell::InvalidateEntry(dictionary, entry); | 5357 auto cell = PropertyCell::InvalidateEntry(dictionary, entry); |
5358 cell->set_value(isolate->heap()->the_hole_value()); | 5358 cell->set_value(isolate->heap()->the_hole_value()); |
5359 // TODO(dcarney): InvalidateForDelete | 5359 // TODO(dcarney): InvalidateForDelete |
5360 dictionary->DetailsAtPut(entry, dictionary->DetailsAt(entry).set_cell_type( | 5360 dictionary->DetailsAtPut(entry, dictionary->DetailsAt(entry).set_cell_type( |
5361 PropertyCellType::kDeleted)); | 5361 PropertyCellType::kInvalidated)); |
5362 return; | 5362 return; |
5363 } | 5363 } |
5364 | 5364 |
5365 NameDictionary::DeleteProperty(dictionary, entry); | 5365 NameDictionary::DeleteProperty(dictionary, entry); |
5366 Handle<NameDictionary> new_properties = | 5366 Handle<NameDictionary> new_properties = |
5367 NameDictionary::Shrink(dictionary, name); | 5367 NameDictionary::Shrink(dictionary, name); |
5368 object->set_properties(*new_properties); | 5368 object->set_properties(*new_properties); |
5369 } | 5369 } |
5370 | 5370 |
5371 | 5371 |
(...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6426 PropertyAttributes attributes) { | 6426 PropertyAttributes attributes) { |
6427 int entry = dictionary->FindEntry(index); | 6427 int entry = dictionary->FindEntry(index); |
6428 if (entry != SeededNumberDictionary::kNotFound) { | 6428 if (entry != SeededNumberDictionary::kNotFound) { |
6429 Object* result = dictionary->ValueAt(entry); | 6429 Object* result = dictionary->ValueAt(entry); |
6430 PropertyDetails details = dictionary->DetailsAt(entry); | 6430 PropertyDetails details = dictionary->DetailsAt(entry); |
6431 if (details.type() == ACCESSOR_CONSTANT && result->IsAccessorPair()) { | 6431 if (details.type() == ACCESSOR_CONSTANT && result->IsAccessorPair()) { |
6432 DCHECK(details.IsConfigurable()); | 6432 DCHECK(details.IsConfigurable()); |
6433 if (details.attributes() != attributes) { | 6433 if (details.attributes() != attributes) { |
6434 dictionary->DetailsAtPut( | 6434 dictionary->DetailsAtPut( |
6435 entry, PropertyDetails(attributes, ACCESSOR_CONSTANT, index, | 6435 entry, PropertyDetails(attributes, ACCESSOR_CONSTANT, index, |
6436 PropertyCellType::kInvalid)); | 6436 PropertyCellType::kNoCell)); |
6437 } | 6437 } |
6438 AccessorPair::cast(result)->SetComponents(getter, setter); | 6438 AccessorPair::cast(result)->SetComponents(getter, setter); |
6439 return true; | 6439 return true; |
6440 } | 6440 } |
6441 } | 6441 } |
6442 return false; | 6442 return false; |
6443 } | 6443 } |
6444 | 6444 |
6445 | 6445 |
6446 void JSObject::DefineElementAccessor(Handle<JSObject> object, | 6446 void JSObject::DefineElementAccessor(Handle<JSObject> object, |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6529 return false; | 6529 return false; |
6530 } | 6530 } |
6531 | 6531 |
6532 | 6532 |
6533 void JSObject::SetElementCallback(Handle<JSObject> object, | 6533 void JSObject::SetElementCallback(Handle<JSObject> object, |
6534 uint32_t index, | 6534 uint32_t index, |
6535 Handle<Object> structure, | 6535 Handle<Object> structure, |
6536 PropertyAttributes attributes) { | 6536 PropertyAttributes attributes) { |
6537 Heap* heap = object->GetHeap(); | 6537 Heap* heap = object->GetHeap(); |
6538 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0, | 6538 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0, |
6539 PropertyCellType::kInvalid); | 6539 PropertyCellType::kNoCell); |
6540 | 6540 |
6541 // Normalize elements to make this operation simple. | 6541 // Normalize elements to make this operation simple. |
6542 bool had_dictionary_elements = object->HasDictionaryElements(); | 6542 bool had_dictionary_elements = object->HasDictionaryElements(); |
6543 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 6543 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
6544 DCHECK(object->HasDictionaryElements() || | 6544 DCHECK(object->HasDictionaryElements() || |
6545 object->HasDictionaryArgumentsElements()); | 6545 object->HasDictionaryArgumentsElements()); |
6546 // Update the dictionary with the new ACCESSOR_CONSTANT property. | 6546 // Update the dictionary with the new ACCESSOR_CONSTANT property. |
6547 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, | 6547 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, |
6548 details); | 6548 details); |
6549 dictionary->set_requires_slow_elements(); | 6549 dictionary->set_requires_slow_elements(); |
(...skipping 6368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12918 // is read-only (a declared const that has not been initialized). | 12918 // is read-only (a declared const that has not been initialized). |
12919 return WriteToReadOnlyProperty( | 12919 return WriteToReadOnlyProperty( |
12920 isolate, object, isolate->factory()->NewNumberFromUint(index), | 12920 isolate, object, isolate->factory()->NewNumberFromUint(index), |
12921 isolate->factory()->undefined_value(), language_mode); | 12921 isolate->factory()->undefined_value(), language_mode); |
12922 } else { | 12922 } else { |
12923 DCHECK(details.IsConfigurable() || !details.IsReadOnly() || | 12923 DCHECK(details.IsConfigurable() || !details.IsReadOnly() || |
12924 element->IsTheHole()); | 12924 element->IsTheHole()); |
12925 dictionary->UpdateMaxNumberKey(index); | 12925 dictionary->UpdateMaxNumberKey(index); |
12926 if (set_mode == DEFINE_PROPERTY) { | 12926 if (set_mode == DEFINE_PROPERTY) { |
12927 details = PropertyDetails(attributes, DATA, details.dictionary_index(), | 12927 details = PropertyDetails(attributes, DATA, details.dictionary_index(), |
12928 PropertyCellType::kInvalid); | 12928 PropertyCellType::kNoCell); |
12929 dictionary->DetailsAtPut(entry, details); | 12929 dictionary->DetailsAtPut(entry, details); |
12930 } | 12930 } |
12931 | 12931 |
12932 // Elements of the arguments object in slow mode might be slow aliases. | 12932 // Elements of the arguments object in slow mode might be slow aliases. |
12933 if (is_arguments && element->IsAliasedArgumentsEntry()) { | 12933 if (is_arguments && element->IsAliasedArgumentsEntry()) { |
12934 Handle<AliasedArgumentsEntry> entry = | 12934 Handle<AliasedArgumentsEntry> entry = |
12935 Handle<AliasedArgumentsEntry>::cast(element); | 12935 Handle<AliasedArgumentsEntry>::cast(element); |
12936 Handle<Context> context(Context::cast(elements->get(0))); | 12936 Handle<Context> context(Context::cast(elements->get(0))); |
12937 int context_index = entry->aliased_context_slot(); | 12937 int context_index = entry->aliased_context_slot(); |
12938 DCHECK(!context->get(context_index)->IsTheHole()); | 12938 DCHECK(!context->get(context_index)->IsTheHole()); |
(...skipping 22 matching lines...) Expand all Loading... |
12961 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12961 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
12962 Handle<String> name = isolate->factory()->NumberToString(number); | 12962 Handle<String> name = isolate->factory()->NumberToString(number); |
12963 Handle<Object> args[] = {name}; | 12963 Handle<Object> args[] = {name}; |
12964 THROW_NEW_ERROR(isolate, | 12964 THROW_NEW_ERROR(isolate, |
12965 NewTypeError("object_not_extensible", | 12965 NewTypeError("object_not_extensible", |
12966 HandleVector(args, arraysize(args))), | 12966 HandleVector(args, arraysize(args))), |
12967 Object); | 12967 Object); |
12968 } | 12968 } |
12969 } | 12969 } |
12970 | 12970 |
12971 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kInvalid); | 12971 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
12972 Handle<SeededNumberDictionary> new_dictionary = | 12972 Handle<SeededNumberDictionary> new_dictionary = |
12973 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, | 12973 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, |
12974 details); | 12974 details); |
12975 if (*dictionary != *new_dictionary) { | 12975 if (*dictionary != *new_dictionary) { |
12976 if (is_arguments) { | 12976 if (is_arguments) { |
12977 elements->set(1, *new_dictionary); | 12977 elements->set(1, *new_dictionary); |
12978 } else { | 12978 } else { |
12979 object->set_elements(*new_dictionary); | 12979 object->set_elements(*new_dictionary); |
12980 } | 12980 } |
12981 dictionary = new_dictionary; | 12981 dictionary = new_dictionary; |
(...skipping 2426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15408 Handle<GlobalObject> global, Handle<Name> name) { | 15408 Handle<GlobalObject> global, Handle<Name> name) { |
15409 DCHECK(!global->HasFastProperties()); | 15409 DCHECK(!global->HasFastProperties()); |
15410 auto dictionary = handle(global->property_dictionary()); | 15410 auto dictionary = handle(global->property_dictionary()); |
15411 int entry = dictionary->FindEntry(name); | 15411 int entry = dictionary->FindEntry(name); |
15412 Handle<PropertyCell> cell; | 15412 Handle<PropertyCell> cell; |
15413 if (entry != NameDictionary::kNotFound) { | 15413 if (entry != NameDictionary::kNotFound) { |
15414 // This call should be idempotent. | 15414 // This call should be idempotent. |
15415 DCHECK(dictionary->DetailsAt(entry).cell_type() == | 15415 DCHECK(dictionary->DetailsAt(entry).cell_type() == |
15416 PropertyCellType::kUninitialized || | 15416 PropertyCellType::kUninitialized || |
15417 dictionary->DetailsAt(entry).cell_type() == | 15417 dictionary->DetailsAt(entry).cell_type() == |
15418 PropertyCellType::kDeleted); | 15418 PropertyCellType::kInvalidated); |
15419 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); | 15419 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); |
15420 cell = handle(PropertyCell::cast(dictionary->ValueAt(entry))); | 15420 cell = handle(PropertyCell::cast(dictionary->ValueAt(entry))); |
15421 DCHECK(cell->value()->IsTheHole()); | 15421 DCHECK(cell->value()->IsTheHole()); |
15422 return cell; | 15422 return cell; |
15423 } | 15423 } |
15424 Isolate* isolate = global->GetIsolate(); | 15424 Isolate* isolate = global->GetIsolate(); |
15425 cell = isolate->factory()->NewPropertyCell(); | 15425 cell = isolate->factory()->NewPropertyCell(); |
15426 PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized); | 15426 PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized); |
15427 dictionary = NameDictionary::Add(dictionary, name, cell, details); | 15427 dictionary = NameDictionary::Add(dictionary, name, cell, details); |
15428 global->set_properties(*dictionary); | 15428 global->set_properties(*dictionary); |
(...skipping 1587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17016 Isolate* isolate = dictionary->GetIsolate(); | 17016 Isolate* isolate = dictionary->GetIsolate(); |
17017 // Swap with a copy. | 17017 // Swap with a copy. |
17018 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); | 17018 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); |
17019 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); | 17019 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
17020 auto new_cell = isolate->factory()->NewPropertyCell(); | 17020 auto new_cell = isolate->factory()->NewPropertyCell(); |
17021 new_cell->set_value(cell->value()); | 17021 new_cell->set_value(cell->value()); |
17022 dictionary->ValueAtPut(entry, *new_cell); | 17022 dictionary->ValueAtPut(entry, *new_cell); |
17023 bool is_the_hole = cell->value()->IsTheHole(); | 17023 bool is_the_hole = cell->value()->IsTheHole(); |
17024 // Cell is officially mutable henceforth. | 17024 // Cell is officially mutable henceforth. |
17025 auto details = dictionary->DetailsAt(entry); | 17025 auto details = dictionary->DetailsAt(entry); |
17026 details = details.set_cell_type(is_the_hole ? PropertyCellType::kDeleted | 17026 details = details.set_cell_type(is_the_hole ? PropertyCellType::kInvalidated |
17027 : PropertyCellType::kMutable); | 17027 : PropertyCellType::kMutable); |
17028 dictionary->DetailsAtPut(entry, details); | 17028 dictionary->DetailsAtPut(entry, details); |
17029 // Old cell is ready for invalidation. | 17029 // Old cell is ready for invalidation. |
17030 if (is_the_hole) { | 17030 if (is_the_hole) { |
17031 cell->set_value(isolate->heap()->undefined_value()); | 17031 cell->set_value(isolate->heap()->undefined_value()); |
17032 } else { | 17032 } else { |
17033 cell->set_value(isolate->heap()->the_hole_value()); | 17033 cell->set_value(isolate->heap()->the_hole_value()); |
17034 } | 17034 } |
17035 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17035 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17036 isolate, DependentCode::kPropertyCellChangedGroup); | 17036 isolate, DependentCode::kPropertyCellChangedGroup); |
17037 return new_cell; | 17037 return new_cell; |
17038 } | 17038 } |
17039 | 17039 |
17040 | 17040 |
| 17041 PropertyCellConstantType PropertyCell::GetConstantType() { |
| 17042 if (value()->IsSmi()) return PropertyCellConstantType::kSmi; |
| 17043 return PropertyCellConstantType::kStableMap; |
| 17044 } |
| 17045 |
| 17046 |
| 17047 static bool RemainsConstantType(Handle<PropertyCell> cell, |
| 17048 Handle<Object> value) { |
| 17049 // TODO(dcarney): double->smi and smi->double transition from kConstant |
| 17050 if (cell->value()->IsSmi() && value->IsSmi()) { |
| 17051 return true; |
| 17052 } else if (cell->value()->IsHeapObject() && value->IsHeapObject()) { |
| 17053 return HeapObject::cast(cell->value())->map() == |
| 17054 HeapObject::cast(*value)->map() && |
| 17055 HeapObject::cast(*value)->map()->is_stable(); |
| 17056 } |
| 17057 return false; |
| 17058 } |
| 17059 |
| 17060 |
17041 PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell, | 17061 PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell, |
17042 Handle<Object> value, | 17062 Handle<Object> value, |
17043 PropertyDetails details) { | 17063 PropertyDetails details) { |
17044 PropertyCellType type = details.cell_type(); | 17064 PropertyCellType type = details.cell_type(); |
17045 DCHECK(!value->IsTheHole()); | 17065 DCHECK(!value->IsTheHole()); |
17046 DCHECK_IMPLIES(cell->value()->IsTheHole(), | 17066 if (cell->value()->IsTheHole()) { |
17047 type == PropertyCellType::kUninitialized || | 17067 switch (type) { |
17048 type == PropertyCellType::kDeleted); | 17068 // Only allow a cell to transition once into constant state. |
| 17069 case PropertyCellType::kUninitialized: |
| 17070 if (value->IsUndefined()) return PropertyCellType::kUndefined; |
| 17071 return PropertyCellType::kConstant; |
| 17072 case PropertyCellType::kInvalidated: |
| 17073 return PropertyCellType::kMutable; |
| 17074 default: |
| 17075 UNREACHABLE(); |
| 17076 return PropertyCellType::kMutable; |
| 17077 } |
| 17078 } |
17049 switch (type) { | 17079 switch (type) { |
17050 // Only allow a cell to transition once into constant state. | |
17051 case PropertyCellType::kUninitialized: | |
17052 if (value->IsUndefined()) return PropertyCellType::kUndefined; | |
17053 return PropertyCellType::kConstant; | |
17054 case PropertyCellType::kUndefined: | 17080 case PropertyCellType::kUndefined: |
17055 return PropertyCellType::kConstant; | 17081 return PropertyCellType::kConstant; |
17056 case PropertyCellType::kConstant: | 17082 case PropertyCellType::kConstant: |
17057 // No transition. | |
17058 if (*value == cell->value()) return PropertyCellType::kConstant; | 17083 if (*value == cell->value()) return PropertyCellType::kConstant; |
17059 // Fall through. | 17084 // Fall through. |
| 17085 case PropertyCellType::kConstantType: |
| 17086 if (RemainsConstantType(cell, value)) { |
| 17087 return PropertyCellType::kConstantType; |
| 17088 } |
| 17089 // Fall through. |
17060 case PropertyCellType::kMutable: | 17090 case PropertyCellType::kMutable: |
17061 return PropertyCellType::kMutable; | 17091 return PropertyCellType::kMutable; |
17062 } | 17092 } |
17063 UNREACHABLE(); | 17093 UNREACHABLE(); |
17064 return PropertyCellType::kMutable; | 17094 return PropertyCellType::kMutable; |
17065 } | 17095 } |
17066 | 17096 |
17067 | 17097 |
17068 Handle<Object> PropertyCell::UpdateCell(Handle<NameDictionary> dictionary, | 17098 Handle<Object> PropertyCell::UpdateCell(Handle<NameDictionary> dictionary, |
17069 int entry, Handle<Object> value, | 17099 int entry, Handle<Object> value, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17102 | 17132 |
17103 auto new_type = UpdatedType(cell, value, original_details); | 17133 auto new_type = UpdatedType(cell, value, original_details); |
17104 if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry); | 17134 if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry); |
17105 | 17135 |
17106 // Install new property details and cell value. | 17136 // Install new property details and cell value. |
17107 details = details.set_cell_type(new_type); | 17137 details = details.set_cell_type(new_type); |
17108 dictionary->DetailsAtPut(entry, details); | 17138 dictionary->DetailsAtPut(entry, details); |
17109 cell->set_value(*value); | 17139 cell->set_value(*value); |
17110 | 17140 |
17111 // Deopt when transitioning from a constant type. | 17141 // Deopt when transitioning from a constant type. |
17112 if (!invalidate && old_type == PropertyCellType::kConstant && | 17142 if (!invalidate && (old_type != new_type)) { |
17113 new_type != PropertyCellType::kConstant) { | |
17114 auto isolate = dictionary->GetIsolate(); | 17143 auto isolate = dictionary->GetIsolate(); |
17115 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17144 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17116 isolate, DependentCode::kPropertyCellChangedGroup); | 17145 isolate, DependentCode::kPropertyCellChangedGroup); |
17117 } | 17146 } |
17118 return value; | 17147 return value; |
17119 } | 17148 } |
17120 | 17149 |
17121 | 17150 |
17122 // static | 17151 // static |
17123 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell, | 17152 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell, |
17124 Handle<Object> new_value) { | 17153 Handle<Object> new_value) { |
17125 if (cell->value() != *new_value) { | 17154 if (cell->value() != *new_value) { |
17126 cell->set_value(*new_value); | 17155 cell->set_value(*new_value); |
17127 Isolate* isolate = cell->GetIsolate(); | 17156 Isolate* isolate = cell->GetIsolate(); |
17128 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17157 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17129 isolate, DependentCode::kPropertyCellChangedGroup); | 17158 isolate, DependentCode::kPropertyCellChangedGroup); |
17130 } | 17159 } |
17131 } | 17160 } |
17132 } } // namespace v8::internal | 17161 } } // namespace v8::internal |
OLD | NEW |