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 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
535 DCHECK(!object->HasFastProperties()); | 535 DCHECK(!object->HasFastProperties()); |
536 Handle<NameDictionary> property_dictionary(object->property_dictionary()); | 536 Handle<NameDictionary> property_dictionary(object->property_dictionary()); |
537 | 537 |
538 if (!name->IsUniqueName()) { | 538 if (!name->IsUniqueName()) { |
539 name = object->GetIsolate()->factory()->InternalizeString( | 539 name = object->GetIsolate()->factory()->InternalizeString( |
540 Handle<String>::cast(name)); | 540 Handle<String>::cast(name)); |
541 } | 541 } |
542 | 542 |
543 int entry = property_dictionary->FindEntry(name); | 543 int entry = property_dictionary->FindEntry(name); |
544 if (entry == NameDictionary::kNotFound) { | 544 if (entry == NameDictionary::kNotFound) { |
545 Handle<Object> store_value = value; | |
546 if (object->IsGlobalObject()) { | 545 if (object->IsGlobalObject()) { |
547 store_value = object->GetIsolate()->factory()->NewPropertyCell(value); | 546 auto cell = object->GetIsolate()->factory()->NewPropertyCell(); |
| 547 cell->set_value(*value); |
| 548 auto cell_type = value->IsUndefined() ? PropertyCellType::kUndefined |
| 549 : PropertyCellType::kConstant; |
| 550 details = details.set_cell_type(cell_type); |
| 551 value = cell; |
548 } | 552 } |
| 553 property_dictionary = |
| 554 NameDictionary::Add(property_dictionary, name, value, details); |
| 555 object->set_properties(*property_dictionary); |
| 556 return; |
| 557 } |
549 | 558 |
550 property_dictionary = NameDictionary::Add( | 559 if (object->IsGlobalObject()) { |
551 property_dictionary, name, store_value, details); | 560 PropertyCell::UpdateCell(property_dictionary, entry, value, details); |
552 object->set_properties(*property_dictionary); | |
553 return; | 561 return; |
554 } | 562 } |
555 | 563 |
556 PropertyDetails original_details = property_dictionary->DetailsAt(entry); | 564 PropertyDetails original_details = property_dictionary->DetailsAt(entry); |
557 int enumeration_index = original_details.dictionary_index(); | 565 int enumeration_index = original_details.dictionary_index(); |
558 | |
559 if (!object->IsGlobalObject()) { | |
560 DCHECK(enumeration_index > 0); | |
561 details = PropertyDetails(details.attributes(), details.type(), | |
562 enumeration_index); | |
563 property_dictionary->SetEntry(entry, name, value, details); | |
564 return; | |
565 } | |
566 | |
567 Handle<PropertyCell> cell( | |
568 PropertyCell::cast(property_dictionary->ValueAt(entry))); | |
569 // Preserve the enumeration index unless the property was deleted. | |
570 if (cell->value()->IsTheHole()) { | |
571 enumeration_index = property_dictionary->NextEnumerationIndex(); | |
572 property_dictionary->SetNextEnumerationIndex(enumeration_index + 1); | |
573 } | |
574 DCHECK(enumeration_index > 0); | 566 DCHECK(enumeration_index > 0); |
575 details = PropertyDetails( | 567 details = details.set_index(enumeration_index); |
576 details.attributes(), details.type(), enumeration_index); | 568 property_dictionary->SetEntry(entry, name, value, details); |
577 PropertyCell::SetValueInferType(cell, value); | |
578 // Please note we have to update the property details. | |
579 property_dictionary->DetailsAtPut(entry, details); | |
580 } | 569 } |
581 | 570 |
582 | 571 |
583 static MaybeHandle<JSObject> FindIndexedAllCanReadHolder( | 572 static MaybeHandle<JSObject> FindIndexedAllCanReadHolder( |
584 Isolate* isolate, Handle<JSObject> js_object, | 573 Isolate* isolate, Handle<JSObject> js_object, |
585 PrototypeIterator::WhereToStart where_to_start) { | 574 PrototypeIterator::WhereToStart where_to_start) { |
586 for (PrototypeIterator iter(isolate, js_object, where_to_start); | 575 for (PrototypeIterator iter(isolate, js_object, where_to_start); |
587 !iter.IsAtEnd(); iter.Advance()) { | 576 !iter.IsAtEnd(); iter.Advance()) { |
588 auto curr = PrototypeIterator::GetCurrent(iter); | 577 auto curr = PrototypeIterator::GetCurrent(iter); |
589 if (!curr->IsJSObject()) break; | 578 if (!curr->IsJSObject()) break; |
(...skipping 1181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1771 } | 1760 } |
1772 | 1761 |
1773 | 1762 |
1774 void JSObject::AddSlowProperty(Handle<JSObject> object, | 1763 void JSObject::AddSlowProperty(Handle<JSObject> object, |
1775 Handle<Name> name, | 1764 Handle<Name> name, |
1776 Handle<Object> value, | 1765 Handle<Object> value, |
1777 PropertyAttributes attributes) { | 1766 PropertyAttributes attributes) { |
1778 DCHECK(!object->HasFastProperties()); | 1767 DCHECK(!object->HasFastProperties()); |
1779 Isolate* isolate = object->GetIsolate(); | 1768 Isolate* isolate = object->GetIsolate(); |
1780 Handle<NameDictionary> dict(object->property_dictionary()); | 1769 Handle<NameDictionary> dict(object->property_dictionary()); |
| 1770 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kInvalid); |
1781 if (object->IsGlobalObject()) { | 1771 if (object->IsGlobalObject()) { |
1782 // In case name is an orphaned property reuse the cell. | |
1783 int entry = dict->FindEntry(name); | 1772 int entry = dict->FindEntry(name); |
| 1773 // If there's a cell there, just invalidate and set the property. |
1784 if (entry != NameDictionary::kNotFound) { | 1774 if (entry != NameDictionary::kNotFound) { |
1785 Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(entry))); | 1775 PropertyCell::UpdateCell(dict, entry, value, details); |
1786 PropertyCell::SetValueInferType(cell, value); | 1776 // TODO(dcarney): move this to UpdateCell. |
1787 // Assign an enumeration index to the property and update | 1777 // Need to adjust the details. |
1788 // SetNextEnumerationIndex. | |
1789 int index = dict->NextEnumerationIndex(); | 1778 int index = dict->NextEnumerationIndex(); |
1790 PropertyDetails details(attributes, DATA, index); | |
1791 dict->SetNextEnumerationIndex(index + 1); | 1779 dict->SetNextEnumerationIndex(index + 1); |
1792 dict->SetEntry(entry, name, cell, details); | 1780 details = dict->DetailsAt(entry).set_index(index); |
| 1781 dict->DetailsAtPut(entry, details); |
1793 return; | 1782 return; |
1794 } | 1783 } |
1795 value = isolate->factory()->NewPropertyCell(value); | 1784 auto cell = isolate->factory()->NewPropertyCell(); |
| 1785 cell->set_value(*value); |
| 1786 auto cell_type = value->IsUndefined() ? PropertyCellType::kUndefined |
| 1787 : PropertyCellType::kConstant; |
| 1788 details = details.set_cell_type(cell_type); |
| 1789 value = cell; |
1796 } | 1790 } |
1797 PropertyDetails details(attributes, DATA, 0); | |
1798 Handle<NameDictionary> result = | 1791 Handle<NameDictionary> result = |
1799 NameDictionary::Add(dict, name, value, details); | 1792 NameDictionary::Add(dict, name, value, details); |
1800 if (*dict != *result) object->set_properties(*result); | 1793 if (*dict != *result) object->set_properties(*result); |
1801 } | 1794 } |
1802 | 1795 |
1803 | 1796 |
1804 Context* JSObject::GetCreationContext() { | 1797 Context* JSObject::GetCreationContext() { |
1805 Object* constructor = this->map()->GetConstructor(); | 1798 Object* constructor = this->map()->GetConstructor(); |
1806 JSFunction* function; | 1799 JSFunction* function; |
1807 if (!constructor->IsJSFunction()) { | 1800 if (!constructor->IsJSFunction()) { |
(...skipping 2799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4607 Handle<NameDictionary> dictionary = | 4600 Handle<NameDictionary> dictionary = |
4608 NameDictionary::New(isolate, property_count); | 4601 NameDictionary::New(isolate, property_count); |
4609 | 4602 |
4610 Handle<DescriptorArray> descs(map->instance_descriptors()); | 4603 Handle<DescriptorArray> descs(map->instance_descriptors()); |
4611 for (int i = 0; i < real_size; i++) { | 4604 for (int i = 0; i < real_size; i++) { |
4612 PropertyDetails details = descs->GetDetails(i); | 4605 PropertyDetails details = descs->GetDetails(i); |
4613 Handle<Name> key(descs->GetKey(i)); | 4606 Handle<Name> key(descs->GetKey(i)); |
4614 switch (details.type()) { | 4607 switch (details.type()) { |
4615 case DATA_CONSTANT: { | 4608 case DATA_CONSTANT: { |
4616 Handle<Object> value(descs->GetConstant(i), isolate); | 4609 Handle<Object> value(descs->GetConstant(i), isolate); |
4617 PropertyDetails d(details.attributes(), DATA, i + 1); | 4610 PropertyDetails d(details.attributes(), DATA, i + 1, |
| 4611 PropertyCellType::kInvalid); |
4618 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4612 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4619 break; | 4613 break; |
4620 } | 4614 } |
4621 case DATA: { | 4615 case DATA: { |
4622 FieldIndex index = FieldIndex::ForDescriptor(*map, i); | 4616 FieldIndex index = FieldIndex::ForDescriptor(*map, i); |
4623 Handle<Object> value; | 4617 Handle<Object> value; |
4624 if (object->IsUnboxedDoubleField(index)) { | 4618 if (object->IsUnboxedDoubleField(index)) { |
4625 double old_value = object->RawFastDoublePropertyAt(index); | 4619 double old_value = object->RawFastDoublePropertyAt(index); |
4626 value = isolate->factory()->NewHeapNumber(old_value); | 4620 value = isolate->factory()->NewHeapNumber(old_value); |
4627 } else { | 4621 } else { |
4628 value = handle(object->RawFastPropertyAt(index), isolate); | 4622 value = handle(object->RawFastPropertyAt(index), isolate); |
4629 if (details.representation().IsDouble()) { | 4623 if (details.representation().IsDouble()) { |
4630 DCHECK(value->IsMutableHeapNumber()); | 4624 DCHECK(value->IsMutableHeapNumber()); |
4631 Handle<HeapNumber> old = Handle<HeapNumber>::cast(value); | 4625 Handle<HeapNumber> old = Handle<HeapNumber>::cast(value); |
4632 value = isolate->factory()->NewHeapNumber(old->value()); | 4626 value = isolate->factory()->NewHeapNumber(old->value()); |
4633 } | 4627 } |
4634 } | 4628 } |
4635 PropertyDetails d(details.attributes(), DATA, i + 1); | 4629 PropertyDetails d(details.attributes(), DATA, i + 1, |
| 4630 PropertyCellType::kInvalid); |
4636 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4631 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4637 break; | 4632 break; |
4638 } | 4633 } |
4639 case ACCESSOR: { | 4634 case ACCESSOR: { |
4640 FieldIndex index = FieldIndex::ForDescriptor(*map, i); | 4635 FieldIndex index = FieldIndex::ForDescriptor(*map, i); |
4641 Handle<Object> value(object->RawFastPropertyAt(index), isolate); | 4636 Handle<Object> value(object->RawFastPropertyAt(index), isolate); |
4642 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1); | 4637 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, |
| 4638 PropertyCellType::kInvalid); |
4643 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4639 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4644 break; | 4640 break; |
4645 } | 4641 } |
4646 case ACCESSOR_CONSTANT: { | 4642 case ACCESSOR_CONSTANT: { |
4647 Handle<Object> value(descs->GetCallbacksObject(i), isolate); | 4643 Handle<Object> value(descs->GetCallbacksObject(i), isolate); |
4648 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1); | 4644 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, |
| 4645 PropertyCellType::kInvalid); |
4649 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4646 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4650 break; | 4647 break; |
4651 } | 4648 } |
4652 } | 4649 } |
4653 } | 4650 } |
4654 | 4651 |
4655 // Copy the next enumeration index from instance descriptor. | 4652 // Copy the next enumeration index from instance descriptor. |
4656 dictionary->SetNextEnumerationIndex(real_size + 1); | 4653 dictionary->SetNextEnumerationIndex(real_size + 1); |
4657 | 4654 |
4658 // From here on we cannot fail and we shouldn't GC anymore. | 4655 // From here on we cannot fail and we shouldn't GC anymore. |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4871 Handle<FixedDoubleArray>::cast(array); | 4868 Handle<FixedDoubleArray>::cast(array); |
4872 if (double_array->is_the_hole(i)) { | 4869 if (double_array->is_the_hole(i)) { |
4873 value = factory->the_hole_value(); | 4870 value = factory->the_hole_value(); |
4874 } else { | 4871 } else { |
4875 value = factory->NewHeapNumber(double_array->get_scalar(i)); | 4872 value = factory->NewHeapNumber(double_array->get_scalar(i)); |
4876 } | 4873 } |
4877 } else { | 4874 } else { |
4878 value = handle(Handle<FixedArray>::cast(array)->get(i), isolate); | 4875 value = handle(Handle<FixedArray>::cast(array)->get(i), isolate); |
4879 } | 4876 } |
4880 if (!value->IsTheHole()) { | 4877 if (!value->IsTheHole()) { |
4881 PropertyDetails details(NONE, DATA, 0); | 4878 PropertyDetails details(NONE, DATA, 0, PropertyCellType::kInvalid); |
4882 dictionary = | 4879 dictionary = |
4883 SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details); | 4880 SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details); |
4884 } | 4881 } |
4885 } | 4882 } |
4886 return dictionary; | 4883 return dictionary; |
4887 } | 4884 } |
4888 | 4885 |
4889 | 4886 |
4890 Handle<SeededNumberDictionary> JSObject::NormalizeElements( | 4887 Handle<SeededNumberDictionary> JSObject::NormalizeElements( |
4891 Handle<JSObject> object) { | 4888 Handle<JSObject> object) { |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5345 | 5342 |
5346 | 5343 |
5347 void JSObject::DeleteNormalizedProperty(Handle<JSObject> object, | 5344 void JSObject::DeleteNormalizedProperty(Handle<JSObject> object, |
5348 Handle<Name> name) { | 5345 Handle<Name> name) { |
5349 DCHECK(!object->HasFastProperties()); | 5346 DCHECK(!object->HasFastProperties()); |
5350 Isolate* isolate = object->GetIsolate(); | 5347 Isolate* isolate = object->GetIsolate(); |
5351 Handle<NameDictionary> dictionary(object->property_dictionary()); | 5348 Handle<NameDictionary> dictionary(object->property_dictionary()); |
5352 int entry = dictionary->FindEntry(name); | 5349 int entry = dictionary->FindEntry(name); |
5353 DCHECK_NE(NameDictionary::kNotFound, entry); | 5350 DCHECK_NE(NameDictionary::kNotFound, entry); |
5354 | 5351 |
5355 // If we have a global object set the cell to the hole. | 5352 // If we have a global object, invalidate the cell and swap in a new one. |
5356 if (object->IsGlobalObject()) { | 5353 if (object->IsGlobalObject()) { |
5357 DCHECK(dictionary->DetailsAt(entry).IsConfigurable()); | 5354 auto cell = PropertyCell::InvalidateEntry(dictionary, entry); |
5358 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); | 5355 cell->set_value(isolate->heap()->the_hole_value()); |
5359 Handle<Object> value = isolate->factory()->the_hole_value(); | 5356 // TODO(dcarney): InvalidateForDelete |
5360 PropertyCell::SetValueInferType(cell, value); | 5357 dictionary->DetailsAtPut(entry, dictionary->DetailsAt(entry).set_cell_type( |
| 5358 PropertyCellType::kDeleted)); |
5361 return; | 5359 return; |
5362 } | 5360 } |
5363 | 5361 |
5364 NameDictionary::DeleteProperty(dictionary, entry); | 5362 NameDictionary::DeleteProperty(dictionary, entry); |
5365 Handle<NameDictionary> new_properties = | 5363 Handle<NameDictionary> new_properties = |
5366 NameDictionary::Shrink(dictionary, name); | 5364 NameDictionary::Shrink(dictionary, name); |
5367 object->set_properties(*new_properties); | 5365 object->set_properties(*new_properties); |
5368 } | 5366 } |
5369 | 5367 |
5370 | 5368 |
(...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6423 Object* setter, | 6421 Object* setter, |
6424 PropertyAttributes attributes) { | 6422 PropertyAttributes attributes) { |
6425 int entry = dictionary->FindEntry(index); | 6423 int entry = dictionary->FindEntry(index); |
6426 if (entry != SeededNumberDictionary::kNotFound) { | 6424 if (entry != SeededNumberDictionary::kNotFound) { |
6427 Object* result = dictionary->ValueAt(entry); | 6425 Object* result = dictionary->ValueAt(entry); |
6428 PropertyDetails details = dictionary->DetailsAt(entry); | 6426 PropertyDetails details = dictionary->DetailsAt(entry); |
6429 if (details.type() == ACCESSOR_CONSTANT && result->IsAccessorPair()) { | 6427 if (details.type() == ACCESSOR_CONSTANT && result->IsAccessorPair()) { |
6430 DCHECK(details.IsConfigurable()); | 6428 DCHECK(details.IsConfigurable()); |
6431 if (details.attributes() != attributes) { | 6429 if (details.attributes() != attributes) { |
6432 dictionary->DetailsAtPut( | 6430 dictionary->DetailsAtPut( |
6433 entry, PropertyDetails(attributes, ACCESSOR_CONSTANT, index)); | 6431 entry, PropertyDetails(attributes, ACCESSOR_CONSTANT, index, |
| 6432 PropertyCellType::kInvalid)); |
6434 } | 6433 } |
6435 AccessorPair::cast(result)->SetComponents(getter, setter); | 6434 AccessorPair::cast(result)->SetComponents(getter, setter); |
6436 return true; | 6435 return true; |
6437 } | 6436 } |
6438 } | 6437 } |
6439 return false; | 6438 return false; |
6440 } | 6439 } |
6441 | 6440 |
6442 | 6441 |
6443 void JSObject::DefineElementAccessor(Handle<JSObject> object, | 6442 void JSObject::DefineElementAccessor(Handle<JSObject> object, |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6525 | 6524 |
6526 return false; | 6525 return false; |
6527 } | 6526 } |
6528 | 6527 |
6529 | 6528 |
6530 void JSObject::SetElementCallback(Handle<JSObject> object, | 6529 void JSObject::SetElementCallback(Handle<JSObject> object, |
6531 uint32_t index, | 6530 uint32_t index, |
6532 Handle<Object> structure, | 6531 Handle<Object> structure, |
6533 PropertyAttributes attributes) { | 6532 PropertyAttributes attributes) { |
6534 Heap* heap = object->GetHeap(); | 6533 Heap* heap = object->GetHeap(); |
6535 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0); | 6534 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0, |
| 6535 PropertyCellType::kInvalid); |
6536 | 6536 |
6537 // Normalize elements to make this operation simple. | 6537 // Normalize elements to make this operation simple. |
6538 bool had_dictionary_elements = object->HasDictionaryElements(); | 6538 bool had_dictionary_elements = object->HasDictionaryElements(); |
6539 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 6539 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
6540 DCHECK(object->HasDictionaryElements() || | 6540 DCHECK(object->HasDictionaryElements() || |
6541 object->HasDictionaryArgumentsElements()); | 6541 object->HasDictionaryArgumentsElements()); |
6542 // Update the dictionary with the new ACCESSOR_CONSTANT property. | 6542 // Update the dictionary with the new ACCESSOR_CONSTANT property. |
6543 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, | 6543 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, |
6544 details); | 6544 details); |
6545 dictionary->set_requires_slow_elements(); | 6545 dictionary->set_requires_slow_elements(); |
(...skipping 24 matching lines...) Expand all Loading... |
6570 void JSObject::SetPropertyCallback(Handle<JSObject> object, | 6570 void JSObject::SetPropertyCallback(Handle<JSObject> object, |
6571 Handle<Name> name, | 6571 Handle<Name> name, |
6572 Handle<Object> structure, | 6572 Handle<Object> structure, |
6573 PropertyAttributes attributes) { | 6573 PropertyAttributes attributes) { |
6574 PropertyNormalizationMode mode = object->map()->is_prototype_map() | 6574 PropertyNormalizationMode mode = object->map()->is_prototype_map() |
6575 ? KEEP_INOBJECT_PROPERTIES | 6575 ? KEEP_INOBJECT_PROPERTIES |
6576 : CLEAR_INOBJECT_PROPERTIES; | 6576 : CLEAR_INOBJECT_PROPERTIES; |
6577 // Normalize object to make this operation simple. | 6577 // Normalize object to make this operation simple. |
6578 NormalizeProperties(object, mode, 0, "SetPropertyCallback"); | 6578 NormalizeProperties(object, mode, 0, "SetPropertyCallback"); |
6579 | 6579 |
6580 // For the global object allocate a new map to invalidate the global inline | |
6581 // caches which have a global property cell reference directly in the code. | |
6582 if (object->IsGlobalObject()) { | |
6583 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); | |
6584 DCHECK(new_map->is_dictionary_map()); | |
6585 #if TRACE_MAPS | |
6586 if (FLAG_trace_maps) { | |
6587 PrintF("[TraceMaps: GlobalPropertyCallback from= %p to= %p ]\n", | |
6588 reinterpret_cast<void*>(object->map()), | |
6589 reinterpret_cast<void*>(*new_map)); | |
6590 } | |
6591 #endif | |
6592 JSObject::MigrateToMap(object, new_map); | |
6593 | |
6594 // When running crankshaft, changing the map is not enough. We | |
6595 // need to deoptimize all functions that rely on this global | |
6596 // object. | |
6597 Deoptimizer::DeoptimizeGlobalObject(*object); | |
6598 } | |
6599 | 6580 |
6600 // Update the dictionary with the new ACCESSOR_CONSTANT property. | 6581 // Update the dictionary with the new ACCESSOR_CONSTANT property. |
6601 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0); | 6582 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0, |
| 6583 PropertyCellType::kMutable); |
6602 SetNormalizedProperty(object, name, structure, details); | 6584 SetNormalizedProperty(object, name, structure, details); |
6603 | 6585 |
6604 ReoptimizeIfPrototype(object); | 6586 ReoptimizeIfPrototype(object); |
6605 } | 6587 } |
6606 | 6588 |
6607 | 6589 |
6608 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object, | 6590 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object, |
6609 Handle<Name> name, | 6591 Handle<Name> name, |
6610 Handle<Object> getter, | 6592 Handle<Object> getter, |
6611 Handle<Object> setter, | 6593 Handle<Object> setter, |
(...skipping 6172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12784 // If a value has not been initialized we allow writing to it even if it | 12766 // If a value has not been initialized we allow writing to it even if it |
12785 // is read-only (a declared const that has not been initialized). | 12767 // is read-only (a declared const that has not been initialized). |
12786 return WriteToReadOnlyProperty( | 12768 return WriteToReadOnlyProperty( |
12787 isolate, object, isolate->factory()->NewNumberFromUint(index), | 12769 isolate, object, isolate->factory()->NewNumberFromUint(index), |
12788 isolate->factory()->undefined_value(), language_mode); | 12770 isolate->factory()->undefined_value(), language_mode); |
12789 } else { | 12771 } else { |
12790 DCHECK(details.IsConfigurable() || !details.IsReadOnly() || | 12772 DCHECK(details.IsConfigurable() || !details.IsReadOnly() || |
12791 element->IsTheHole()); | 12773 element->IsTheHole()); |
12792 dictionary->UpdateMaxNumberKey(index); | 12774 dictionary->UpdateMaxNumberKey(index); |
12793 if (set_mode == DEFINE_PROPERTY) { | 12775 if (set_mode == DEFINE_PROPERTY) { |
12794 details = PropertyDetails(attributes, DATA, details.dictionary_index()); | 12776 details = PropertyDetails(attributes, DATA, details.dictionary_index(), |
| 12777 PropertyCellType::kInvalid); |
12795 dictionary->DetailsAtPut(entry, details); | 12778 dictionary->DetailsAtPut(entry, details); |
12796 } | 12779 } |
12797 | 12780 |
12798 // Elements of the arguments object in slow mode might be slow aliases. | 12781 // Elements of the arguments object in slow mode might be slow aliases. |
12799 if (is_arguments && element->IsAliasedArgumentsEntry()) { | 12782 if (is_arguments && element->IsAliasedArgumentsEntry()) { |
12800 Handle<AliasedArgumentsEntry> entry = | 12783 Handle<AliasedArgumentsEntry> entry = |
12801 Handle<AliasedArgumentsEntry>::cast(element); | 12784 Handle<AliasedArgumentsEntry>::cast(element); |
12802 Handle<Context> context(Context::cast(elements->get(0))); | 12785 Handle<Context> context(Context::cast(elements->get(0))); |
12803 int context_index = entry->aliased_context_slot(); | 12786 int context_index = entry->aliased_context_slot(); |
12804 DCHECK(!context->get(context_index)->IsTheHole()); | 12787 DCHECK(!context->get(context_index)->IsTheHole()); |
(...skipping 22 matching lines...) Expand all Loading... |
12827 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12810 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
12828 Handle<String> name = isolate->factory()->NumberToString(number); | 12811 Handle<String> name = isolate->factory()->NumberToString(number); |
12829 Handle<Object> args[] = {name}; | 12812 Handle<Object> args[] = {name}; |
12830 THROW_NEW_ERROR(isolate, | 12813 THROW_NEW_ERROR(isolate, |
12831 NewTypeError("object_not_extensible", | 12814 NewTypeError("object_not_extensible", |
12832 HandleVector(args, arraysize(args))), | 12815 HandleVector(args, arraysize(args))), |
12833 Object); | 12816 Object); |
12834 } | 12817 } |
12835 } | 12818 } |
12836 | 12819 |
12837 PropertyDetails details(attributes, DATA, 0); | 12820 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kInvalid); |
12838 Handle<SeededNumberDictionary> new_dictionary = | 12821 Handle<SeededNumberDictionary> new_dictionary = |
12839 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, | 12822 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, |
12840 details); | 12823 details); |
12841 if (*dictionary != *new_dictionary) { | 12824 if (*dictionary != *new_dictionary) { |
12842 if (is_arguments) { | 12825 if (is_arguments) { |
12843 elements->set(1, *new_dictionary); | 12826 elements->set(1, *new_dictionary); |
12844 } else { | 12827 } else { |
12845 object->set_elements(*new_dictionary); | 12828 object->set_elements(*new_dictionary); |
12846 } | 12829 } |
12847 dictionary = new_dictionary; | 12830 dictionary = new_dictionary; |
(...skipping 2064 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14912 return bailout; | 14895 return bailout; |
14913 } else { | 14896 } else { |
14914 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( | 14897 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( |
14915 new_dict, key, value, details); | 14898 new_dict, key, value, details); |
14916 DCHECK(result.is_identical_to(new_dict)); | 14899 DCHECK(result.is_identical_to(new_dict)); |
14917 USE(result); | 14900 USE(result); |
14918 } | 14901 } |
14919 } | 14902 } |
14920 | 14903 |
14921 uint32_t result = pos; | 14904 uint32_t result = pos; |
14922 PropertyDetails no_details(NONE, DATA, 0); | 14905 PropertyDetails no_details(NONE, DATA, 0, PropertyCellType::kInvalid); |
14923 while (undefs > 0) { | 14906 while (undefs > 0) { |
14924 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { | 14907 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { |
14925 // Adding an entry with the key beyond smi-range requires | 14908 // Adding an entry with the key beyond smi-range requires |
14926 // allocation. Bailout. | 14909 // allocation. Bailout. |
14927 return bailout; | 14910 return bailout; |
14928 } | 14911 } |
14929 HandleScope scope(isolate); | 14912 HandleScope scope(isolate); |
14930 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( | 14913 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( |
14931 new_dict, pos, isolate->factory()->undefined_value(), no_details); | 14914 new_dict, pos, isolate->factory()->undefined_value(), no_details); |
14932 DCHECK(result.is_identical_to(new_dict)); | 14915 DCHECK(result.is_identical_to(new_dict)); |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15273 } | 15256 } |
15274 array->set(index, double_value); | 15257 array->set(index, double_value); |
15275 } | 15258 } |
15276 return array->GetIsolate()->factory()->NewNumber(double_value); | 15259 return array->GetIsolate()->factory()->NewNumber(double_value); |
15277 } | 15260 } |
15278 | 15261 |
15279 | 15262 |
15280 void GlobalObject::InvalidatePropertyCell(Handle<GlobalObject> global, | 15263 void GlobalObject::InvalidatePropertyCell(Handle<GlobalObject> global, |
15281 Handle<Name> name) { | 15264 Handle<Name> name) { |
15282 DCHECK(!global->HasFastProperties()); | 15265 DCHECK(!global->HasFastProperties()); |
15283 Isolate* isolate = global->GetIsolate(); | 15266 auto dictionary = handle(global->property_dictionary()); |
15284 int entry = global->property_dictionary()->FindEntry(name); | 15267 int entry = dictionary->FindEntry(name); |
15285 if (entry != NameDictionary::kNotFound) { | 15268 if (entry == NameDictionary::kNotFound) return; |
15286 Handle<PropertyCell> cell( | 15269 PropertyCell::InvalidateEntry(dictionary, entry); |
15287 PropertyCell::cast(global->property_dictionary()->ValueAt(entry))); | |
15288 | |
15289 Handle<Object> value(cell->value(), isolate); | |
15290 Handle<PropertyCell> new_cell = isolate->factory()->NewPropertyCell(value); | |
15291 global->property_dictionary()->ValueAtPut(entry, *new_cell); | |
15292 | |
15293 Handle<Object> hole = isolate->factory()->the_hole_value(); | |
15294 if (*hole != *value) { | |
15295 PropertyCell::SetValueInferType(cell, hole); | |
15296 } else { | |
15297 // If property value was the hole, set it to any other value, | |
15298 // to ensure that LoadNonexistent ICs execute a miss. | |
15299 Handle<Object> undefined = isolate->factory()->undefined_value(); | |
15300 PropertyCell::SetValueInferType(cell, undefined); | |
15301 } | |
15302 } | |
15303 } | 15270 } |
15304 | 15271 |
15305 | 15272 |
| 15273 // TODO(dcarney): rename to EnsureEmptyPropertyCell or something. |
15306 Handle<PropertyCell> GlobalObject::EnsurePropertyCell( | 15274 Handle<PropertyCell> GlobalObject::EnsurePropertyCell( |
15307 Handle<GlobalObject> global, Handle<Name> name) { | 15275 Handle<GlobalObject> global, Handle<Name> name) { |
15308 DCHECK(!global->HasFastProperties()); | 15276 DCHECK(!global->HasFastProperties()); |
15309 int entry = global->property_dictionary()->FindEntry(name); | 15277 auto dictionary = handle(global->property_dictionary()); |
15310 if (entry == NameDictionary::kNotFound) { | 15278 int entry = dictionary->FindEntry(name); |
15311 Isolate* isolate = global->GetIsolate(); | 15279 Handle<PropertyCell> cell; |
15312 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCellWithHole(); | 15280 if (entry != NameDictionary::kNotFound) { |
15313 PropertyDetails details(NONE, DATA, 0); | 15281 // Allow this call to be idempotent. |
15314 Handle<NameDictionary> dictionary = NameDictionary::Add( | 15282 auto type = dictionary->DetailsAt(entry).cell_type(); |
15315 handle(global->property_dictionary()), name, cell, details); | 15283 if (type == PropertyCellType::kUninitialized || |
15316 global->set_properties(*dictionary); | 15284 type == PropertyCellType::kDeleted) { |
| 15285 cell = handle(PropertyCell::cast(dictionary->ValueAt(entry))); |
| 15286 } else { |
| 15287 CHECK(false); |
| 15288 cell = PropertyCell::InvalidateEntry(dictionary, entry); |
| 15289 } |
| 15290 DCHECK(cell->value()->IsTheHole()); |
15317 return cell; | 15291 return cell; |
15318 } else { | |
15319 Object* value = global->property_dictionary()->ValueAt(entry); | |
15320 DCHECK(value->IsPropertyCell()); | |
15321 return handle(PropertyCell::cast(value)); | |
15322 } | 15292 } |
| 15293 Isolate* isolate = global->GetIsolate(); |
| 15294 cell = isolate->factory()->NewPropertyCell(); |
| 15295 PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized); |
| 15296 dictionary = NameDictionary::Add(dictionary, name, cell, details); |
| 15297 global->set_properties(*dictionary); |
| 15298 return cell; |
15323 } | 15299 } |
15324 | 15300 |
15325 | 15301 |
15326 // This class is used for looking up two character strings in the string table. | 15302 // This class is used for looking up two character strings in the string table. |
15327 // If we don't have a hit we don't want to waste much time so we unroll the | 15303 // If we don't have a hit we don't want to waste much time so we unroll the |
15328 // string hash calculation loop here for speed. Doesn't work if the two | 15304 // string hash calculation loop here for speed. Doesn't work if the two |
15329 // characters form a decimal integer, since such strings have a different hash | 15305 // characters form a decimal integer, since such strings have a different hash |
15330 // algorithm. | 15306 // algorithm. |
15331 class TwoCharHashTableKey : public HashTableKey { | 15307 class TwoCharHashTableKey : public HashTableKey { |
15332 public: | 15308 public: |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15722 | 15698 |
15723 // Iterate over the dictionary using the enumeration order and update | 15699 // Iterate over the dictionary using the enumeration order and update |
15724 // the dictionary with new enumeration indices. | 15700 // the dictionary with new enumeration indices. |
15725 for (int i = 0; i < length; i++) { | 15701 for (int i = 0; i < length; i++) { |
15726 int index = Smi::cast(iteration_order->get(i))->value(); | 15702 int index = Smi::cast(iteration_order->get(i))->value(); |
15727 DCHECK(dictionary->IsKey(dictionary->KeyAt(index))); | 15703 DCHECK(dictionary->IsKey(dictionary->KeyAt(index))); |
15728 | 15704 |
15729 int enum_index = PropertyDetails::kInitialIndex + i; | 15705 int enum_index = PropertyDetails::kInitialIndex + i; |
15730 | 15706 |
15731 PropertyDetails details = dictionary->DetailsAt(index); | 15707 PropertyDetails details = dictionary->DetailsAt(index); |
15732 PropertyDetails new_details = | 15708 PropertyDetails new_details = details.set_index(enum_index); |
15733 PropertyDetails(details.attributes(), details.type(), enum_index); | |
15734 dictionary->DetailsAtPut(index, new_details); | 15709 dictionary->DetailsAtPut(index, new_details); |
15735 } | 15710 } |
15736 | 15711 |
15737 // Set the next enumeration index. | 15712 // Set the next enumeration index. |
15738 dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length); | 15713 dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length); |
15739 return iteration_order; | 15714 return iteration_order; |
15740 } | 15715 } |
15741 | 15716 |
15742 | 15717 |
15743 template<typename Derived, typename Shape, typename Key> | 15718 template<typename Derived, typename Shape, typename Key> |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15776 if (entry != Dictionary::kNotFound) { | 15751 if (entry != Dictionary::kNotFound) { |
15777 dictionary->ValueAtPut(entry, *value); | 15752 dictionary->ValueAtPut(entry, *value); |
15778 return dictionary; | 15753 return dictionary; |
15779 } | 15754 } |
15780 | 15755 |
15781 // Check whether the dictionary should be extended. | 15756 // Check whether the dictionary should be extended. |
15782 dictionary = EnsureCapacity(dictionary, 1, key); | 15757 dictionary = EnsureCapacity(dictionary, 1, key); |
15783 #ifdef DEBUG | 15758 #ifdef DEBUG |
15784 USE(Shape::AsHandle(dictionary->GetIsolate(), key)); | 15759 USE(Shape::AsHandle(dictionary->GetIsolate(), key)); |
15785 #endif | 15760 #endif |
15786 PropertyDetails details(NONE, DATA, 0); | 15761 PropertyDetails details(NONE, DATA, 0, PropertyCellType::kInvalid); |
15787 | 15762 |
15788 AddEntry(dictionary, key, value, details, dictionary->Hash(key)); | 15763 AddEntry(dictionary, key, value, details, dictionary->Hash(key)); |
15789 return dictionary; | 15764 return dictionary; |
15790 } | 15765 } |
15791 | 15766 |
15792 | 15767 |
15793 template<typename Derived, typename Shape, typename Key> | 15768 template<typename Derived, typename Shape, typename Key> |
15794 Handle<Derived> Dictionary<Derived, Shape, Key>::Add( | 15769 Handle<Derived> Dictionary<Derived, Shape, Key>::Add( |
15795 Handle<Derived> dictionary, | 15770 Handle<Derived> dictionary, |
15796 Key key, | 15771 Key key, |
(...skipping 19 matching lines...) Expand all Loading... |
15816 uint32_t hash) { | 15791 uint32_t hash) { |
15817 // Compute the key object. | 15792 // Compute the key object. |
15818 Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key); | 15793 Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key); |
15819 | 15794 |
15820 uint32_t entry = dictionary->FindInsertionEntry(hash); | 15795 uint32_t entry = dictionary->FindInsertionEntry(hash); |
15821 // Insert element at empty or deleted entry | 15796 // Insert element at empty or deleted entry |
15822 if (details.dictionary_index() == 0 && Shape::kIsEnumerable) { | 15797 if (details.dictionary_index() == 0 && Shape::kIsEnumerable) { |
15823 // Assign an enumeration index to the property and update | 15798 // Assign an enumeration index to the property and update |
15824 // SetNextEnumerationIndex. | 15799 // SetNextEnumerationIndex. |
15825 int index = dictionary->NextEnumerationIndex(); | 15800 int index = dictionary->NextEnumerationIndex(); |
15826 details = PropertyDetails(details.attributes(), details.type(), index); | 15801 details = details.set_index(index); |
15827 dictionary->SetNextEnumerationIndex(index + 1); | 15802 dictionary->SetNextEnumerationIndex(index + 1); |
15828 } | 15803 } |
15829 dictionary->SetEntry(entry, k, value, details); | 15804 dictionary->SetEntry(entry, k, value, details); |
15830 DCHECK((dictionary->KeyAt(entry)->IsNumber() || | 15805 DCHECK((dictionary->KeyAt(entry)->IsNumber() || |
15831 dictionary->KeyAt(entry)->IsName())); | 15806 dictionary->KeyAt(entry)->IsName())); |
15832 dictionary->ElementAdded(); | 15807 dictionary->ElementAdded(); |
15833 } | 15808 } |
15834 | 15809 |
15835 | 15810 |
15836 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) { | 15811 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) { |
(...skipping 25 matching lines...) Expand all Loading... |
15862 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); | 15837 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); |
15863 return Add(dictionary, key, value, details); | 15838 return Add(dictionary, key, value, details); |
15864 } | 15839 } |
15865 | 15840 |
15866 | 15841 |
15867 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry( | 15842 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry( |
15868 Handle<UnseededNumberDictionary> dictionary, | 15843 Handle<UnseededNumberDictionary> dictionary, |
15869 uint32_t key, | 15844 uint32_t key, |
15870 Handle<Object> value) { | 15845 Handle<Object> value) { |
15871 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); | 15846 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); |
15872 return Add(dictionary, key, value, PropertyDetails(NONE, DATA, 0)); | 15847 return Add(dictionary, key, value, |
| 15848 PropertyDetails(NONE, DATA, 0, PropertyCellType::kInvalid)); |
15873 } | 15849 } |
15874 | 15850 |
15875 | 15851 |
15876 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut( | 15852 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut( |
15877 Handle<SeededNumberDictionary> dictionary, | 15853 Handle<SeededNumberDictionary> dictionary, |
15878 uint32_t key, | 15854 uint32_t key, |
15879 Handle<Object> value) { | 15855 Handle<Object> value) { |
15880 dictionary->UpdateMaxNumberKey(key); | 15856 dictionary->UpdateMaxNumberKey(key); |
15881 return AtPut(dictionary, key, value); | 15857 return AtPut(dictionary, key, value); |
15882 } | 15858 } |
(...skipping 10 matching lines...) Expand all Loading... |
15893 Handle<SeededNumberDictionary> SeededNumberDictionary::Set( | 15869 Handle<SeededNumberDictionary> SeededNumberDictionary::Set( |
15894 Handle<SeededNumberDictionary> dictionary, | 15870 Handle<SeededNumberDictionary> dictionary, |
15895 uint32_t key, | 15871 uint32_t key, |
15896 Handle<Object> value, | 15872 Handle<Object> value, |
15897 PropertyDetails details) { | 15873 PropertyDetails details) { |
15898 int entry = dictionary->FindEntry(key); | 15874 int entry = dictionary->FindEntry(key); |
15899 if (entry == kNotFound) { | 15875 if (entry == kNotFound) { |
15900 return AddNumberEntry(dictionary, key, value, details); | 15876 return AddNumberEntry(dictionary, key, value, details); |
15901 } | 15877 } |
15902 // Preserve enumeration index. | 15878 // Preserve enumeration index. |
15903 details = PropertyDetails(details.attributes(), | 15879 details = details.set_index(dictionary->DetailsAt(entry).dictionary_index()); |
15904 details.type(), | |
15905 dictionary->DetailsAt(entry).dictionary_index()); | |
15906 Handle<Object> object_key = | 15880 Handle<Object> object_key = |
15907 SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key); | 15881 SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key); |
15908 dictionary->SetEntry(entry, object_key, value, details); | 15882 dictionary->SetEntry(entry, object_key, value, details); |
15909 return dictionary; | 15883 return dictionary; |
15910 } | 15884 } |
15911 | 15885 |
15912 | 15886 |
15913 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set( | 15887 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set( |
15914 Handle<UnseededNumberDictionary> dictionary, | 15888 Handle<UnseededNumberDictionary> dictionary, |
15915 uint32_t key, | 15889 uint32_t key, |
(...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17073 Handle<Object> result(buffer(), GetIsolate()); | 17047 Handle<Object> result(buffer(), GetIsolate()); |
17074 if (*result != Smi::FromInt(0)) { | 17048 if (*result != Smi::FromInt(0)) { |
17075 DCHECK(IsExternalArrayElementsKind(map()->elements_kind())); | 17049 DCHECK(IsExternalArrayElementsKind(map()->elements_kind())); |
17076 return Handle<JSArrayBuffer>::cast(result); | 17050 return Handle<JSArrayBuffer>::cast(result); |
17077 } | 17051 } |
17078 Handle<JSTypedArray> self(this); | 17052 Handle<JSTypedArray> self(this); |
17079 return MaterializeArrayBuffer(self); | 17053 return MaterializeArrayBuffer(self); |
17080 } | 17054 } |
17081 | 17055 |
17082 | 17056 |
17083 HeapType* PropertyCell::type() { | 17057 Handle<PropertyCell> PropertyCell::InvalidateEntry( |
17084 return static_cast<HeapType*>(type_raw()); | 17058 Handle<NameDictionary> dictionary, int entry) { |
| 17059 Isolate* isolate = dictionary->GetIsolate(); |
| 17060 // Swap with a copy. |
| 17061 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
| 17062 auto new_cell = isolate->factory()->NewPropertyCell(); |
| 17063 new_cell->set_value(cell->value()); |
| 17064 dictionary->ValueAtPut(entry, *new_cell); |
| 17065 bool is_the_hole = cell->value()->IsTheHole(); |
| 17066 // Cell is officially mutable henceforth. |
| 17067 auto details = dictionary->DetailsAt(entry); |
| 17068 details = details.set_cell_type(is_the_hole ? PropertyCellType::kDeleted |
| 17069 : PropertyCellType::kMutable); |
| 17070 dictionary->DetailsAtPut(entry, details); |
| 17071 // Old cell is ready for invalidation. |
| 17072 if (is_the_hole) { |
| 17073 cell->set_value(isolate->heap()->undefined_value()); |
| 17074 } else { |
| 17075 cell->set_value(isolate->heap()->the_hole_value()); |
| 17076 } |
| 17077 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 17078 isolate, DependentCode::kPropertyCellChangedGroup); |
| 17079 return new_cell; |
17085 } | 17080 } |
17086 | 17081 |
17087 | 17082 |
17088 void PropertyCell::set_type(HeapType* type, WriteBarrierMode ignored) { | 17083 PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell, |
17089 DCHECK(IsPropertyCell()); | 17084 Handle<Object> value, |
17090 set_type_raw(type, ignored); | 17085 PropertyDetails details) { |
| 17086 PropertyCellType type = details.cell_type(); |
| 17087 DCHECK(!value->IsTheHole()); |
| 17088 DCHECK_IMPLIES(cell->value()->IsTheHole(), |
| 17089 type == PropertyCellType::kUninitialized || |
| 17090 type == PropertyCellType::kDeleted); |
| 17091 switch (type) { |
| 17092 // Only allow a cell to transition once into constant state. |
| 17093 case PropertyCellType::kUninitialized: |
| 17094 if (value->IsUndefined()) return PropertyCellType::kUndefined; |
| 17095 return PropertyCellType::kConstant; |
| 17096 case PropertyCellType::kUndefined: |
| 17097 return PropertyCellType::kConstant; |
| 17098 case PropertyCellType::kConstant: |
| 17099 // No transition. |
| 17100 if (*value == cell->value()) return PropertyCellType::kConstant; |
| 17101 // Fall through. |
| 17102 case PropertyCellType::kMutable: |
| 17103 return PropertyCellType::kMutable; |
| 17104 } |
| 17105 UNREACHABLE(); |
| 17106 return PropertyCellType::kMutable; |
17091 } | 17107 } |
17092 | 17108 |
17093 | 17109 |
17094 Handle<HeapType> PropertyCell::UpdatedType(Handle<PropertyCell> cell, | 17110 Handle<Object> PropertyCell::UpdateCell(Handle<NameDictionary> dictionary, |
17095 Handle<Object> value) { | 17111 int entry, Handle<Object> value, |
17096 Isolate* isolate = cell->GetIsolate(); | 17112 PropertyDetails details) { |
17097 Handle<HeapType> old_type(cell->type(), isolate); | 17113 DCHECK(!value->IsTheHole()); |
17098 Handle<HeapType> new_type = HeapType::Constant(value, isolate); | 17114 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
| 17115 const PropertyDetails original_details = dictionary->DetailsAt(entry); |
| 17116 // Data accesses could be cached in ics or optimized code. |
| 17117 bool invalidate = |
| 17118 original_details.kind() == kData && details.kind() == kAccessor; |
| 17119 int index = original_details.dictionary_index(); |
| 17120 auto old_type = original_details.cell_type(); |
| 17121 // Preserve the enumeration index unless the property was deleted or never |
| 17122 // initialized. |
| 17123 if (cell->value()->IsTheHole()) { |
| 17124 index = dictionary->NextEnumerationIndex(); |
| 17125 dictionary->SetNextEnumerationIndex(index + 1); |
| 17126 // Negative lookup cells must be invalidated. |
| 17127 invalidate = true; |
| 17128 } |
| 17129 DCHECK(index > 0); |
| 17130 details = details.set_index(index); |
17099 | 17131 |
17100 if (new_type->Is(old_type)) return old_type; | |
17101 | |
17102 cell->dependent_code()->DeoptimizeDependentCodeGroup( | |
17103 isolate, DependentCode::kPropertyCellChangedGroup); | |
17104 | |
17105 if (old_type->Is(HeapType::None()) || old_type->Is(HeapType::Undefined())) { | |
17106 return new_type; | |
17107 } | |
17108 | |
17109 return HeapType::Any(isolate); | |
17110 } | |
17111 | |
17112 | |
17113 Handle<Object> PropertyCell::SetValueInferType(Handle<PropertyCell> cell, | |
17114 Handle<Object> value) { | |
17115 // Heuristic: if a small-ish string is stored in a previously uninitialized | 17132 // Heuristic: if a small-ish string is stored in a previously uninitialized |
17116 // property cell, internalize it. | 17133 // property cell, internalize it. |
17117 const int kMaxLengthForInternalization = 200; | 17134 const int kMaxLengthForInternalization = 200; |
17118 if ((cell->type()->Is(HeapType::None()) || | 17135 if ((old_type == PropertyCellType::kUninitialized || |
17119 cell->type()->Is(HeapType::Undefined())) && | 17136 old_type == PropertyCellType::kUndefined) && |
17120 value->IsString()) { | 17137 value->IsString()) { |
17121 auto string = Handle<String>::cast(value); | 17138 auto string = Handle<String>::cast(value); |
17122 if (string->length() <= kMaxLengthForInternalization && | 17139 if (string->length() <= kMaxLengthForInternalization) { |
17123 !string->map()->is_undetectable()) { | |
17124 value = cell->GetIsolate()->factory()->InternalizeString(string); | 17140 value = cell->GetIsolate()->factory()->InternalizeString(string); |
17125 } | 17141 } |
17126 } | 17142 } |
| 17143 |
| 17144 auto new_type = UpdatedType(cell, value, original_details); |
| 17145 if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry); |
| 17146 |
| 17147 // Install new property details and cell value. |
| 17148 details = details.set_cell_type(new_type); |
| 17149 dictionary->DetailsAtPut(entry, details); |
17127 cell->set_value(*value); | 17150 cell->set_value(*value); |
17128 if (!HeapType::Any()->Is(cell->type())) { | 17151 |
17129 Handle<HeapType> new_type = UpdatedType(cell, value); | 17152 // Deopt when transitioning from a constant type. |
17130 cell->set_type(*new_type); | 17153 if (!invalidate && old_type == PropertyCellType::kConstant && |
| 17154 new_type != PropertyCellType::kConstant) { |
| 17155 auto isolate = dictionary->GetIsolate(); |
| 17156 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 17157 isolate, DependentCode::kPropertyCellChangedGroup); |
17131 } | 17158 } |
17132 return value; | 17159 return value; |
17133 } | 17160 } |
17134 | 17161 |
17135 | 17162 |
17136 // static | 17163 // static |
17137 void PropertyCell::AddDependentCompilationInfo(Handle<PropertyCell> cell, | 17164 void PropertyCell::AddDependentCompilationInfo(Handle<PropertyCell> cell, |
17138 CompilationInfo* info) { | 17165 CompilationInfo* info) { |
17139 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( | 17166 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( |
17140 handle(cell->dependent_code(), info->isolate()), | 17167 handle(cell->dependent_code(), info->isolate()), |
17141 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); | 17168 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); |
17142 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 17169 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
17143 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 17170 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
17144 cell, info->zone()); | 17171 cell, info->zone()); |
17145 } | 17172 } |
17146 | 17173 |
17147 } } // namespace v8::internal | 17174 } } // namespace v8::internal |
OLD | NEW |