| 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 |