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 2741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4549 Handle<NameDictionary> dictionary = | 4542 Handle<NameDictionary> dictionary = |
4550 NameDictionary::New(isolate, property_count); | 4543 NameDictionary::New(isolate, property_count); |
4551 | 4544 |
4552 Handle<DescriptorArray> descs(map->instance_descriptors()); | 4545 Handle<DescriptorArray> descs(map->instance_descriptors()); |
4553 for (int i = 0; i < real_size; i++) { | 4546 for (int i = 0; i < real_size; i++) { |
4554 PropertyDetails details = descs->GetDetails(i); | 4547 PropertyDetails details = descs->GetDetails(i); |
4555 Handle<Name> key(descs->GetKey(i)); | 4548 Handle<Name> key(descs->GetKey(i)); |
4556 switch (details.type()) { | 4549 switch (details.type()) { |
4557 case DATA_CONSTANT: { | 4550 case DATA_CONSTANT: { |
4558 Handle<Object> value(descs->GetConstant(i), isolate); | 4551 Handle<Object> value(descs->GetConstant(i), isolate); |
4559 PropertyDetails d(details.attributes(), DATA, i + 1); | 4552 PropertyDetails d(details.attributes(), DATA, i + 1, |
| 4553 PropertyCellType::kInvalid); |
4560 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4554 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4561 break; | 4555 break; |
4562 } | 4556 } |
4563 case DATA: { | 4557 case DATA: { |
4564 FieldIndex index = FieldIndex::ForDescriptor(*map, i); | 4558 FieldIndex index = FieldIndex::ForDescriptor(*map, i); |
4565 Handle<Object> value; | 4559 Handle<Object> value; |
4566 if (object->IsUnboxedDoubleField(index)) { | 4560 if (object->IsUnboxedDoubleField(index)) { |
4567 double old_value = object->RawFastDoublePropertyAt(index); | 4561 double old_value = object->RawFastDoublePropertyAt(index); |
4568 value = isolate->factory()->NewHeapNumber(old_value); | 4562 value = isolate->factory()->NewHeapNumber(old_value); |
4569 } else { | 4563 } else { |
4570 value = handle(object->RawFastPropertyAt(index), isolate); | 4564 value = handle(object->RawFastPropertyAt(index), isolate); |
4571 if (details.representation().IsDouble()) { | 4565 if (details.representation().IsDouble()) { |
4572 DCHECK(value->IsMutableHeapNumber()); | 4566 DCHECK(value->IsMutableHeapNumber()); |
4573 Handle<HeapNumber> old = Handle<HeapNumber>::cast(value); | 4567 Handle<HeapNumber> old = Handle<HeapNumber>::cast(value); |
4574 value = isolate->factory()->NewHeapNumber(old->value()); | 4568 value = isolate->factory()->NewHeapNumber(old->value()); |
4575 } | 4569 } |
4576 } | 4570 } |
4577 PropertyDetails d(details.attributes(), DATA, i + 1); | 4571 PropertyDetails d(details.attributes(), DATA, i + 1, |
| 4572 PropertyCellType::kInvalid); |
4578 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4573 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4579 break; | 4574 break; |
4580 } | 4575 } |
4581 case ACCESSOR: { | 4576 case ACCESSOR: { |
4582 FieldIndex index = FieldIndex::ForDescriptor(*map, i); | 4577 FieldIndex index = FieldIndex::ForDescriptor(*map, i); |
4583 Handle<Object> value(object->RawFastPropertyAt(index), isolate); | 4578 Handle<Object> value(object->RawFastPropertyAt(index), isolate); |
4584 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1); | 4579 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, |
| 4580 PropertyCellType::kInvalid); |
4585 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4581 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4586 break; | 4582 break; |
4587 } | 4583 } |
4588 case ACCESSOR_CONSTANT: { | 4584 case ACCESSOR_CONSTANT: { |
4589 Handle<Object> value(descs->GetCallbacksObject(i), isolate); | 4585 Handle<Object> value(descs->GetCallbacksObject(i), isolate); |
4590 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1); | 4586 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, |
| 4587 PropertyCellType::kInvalid); |
4591 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4588 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4592 break; | 4589 break; |
4593 } | 4590 } |
4594 } | 4591 } |
4595 } | 4592 } |
4596 | 4593 |
4597 // Copy the next enumeration index from instance descriptor. | 4594 // Copy the next enumeration index from instance descriptor. |
4598 dictionary->SetNextEnumerationIndex(real_size + 1); | 4595 dictionary->SetNextEnumerationIndex(real_size + 1); |
4599 | 4596 |
4600 // From here on we cannot fail and we shouldn't GC anymore. | 4597 // 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... |
4813 Handle<FixedDoubleArray>::cast(array); | 4810 Handle<FixedDoubleArray>::cast(array); |
4814 if (double_array->is_the_hole(i)) { | 4811 if (double_array->is_the_hole(i)) { |
4815 value = factory->the_hole_value(); | 4812 value = factory->the_hole_value(); |
4816 } else { | 4813 } else { |
4817 value = factory->NewHeapNumber(double_array->get_scalar(i)); | 4814 value = factory->NewHeapNumber(double_array->get_scalar(i)); |
4818 } | 4815 } |
4819 } else { | 4816 } else { |
4820 value = handle(Handle<FixedArray>::cast(array)->get(i), isolate); | 4817 value = handle(Handle<FixedArray>::cast(array)->get(i), isolate); |
4821 } | 4818 } |
4822 if (!value->IsTheHole()) { | 4819 if (!value->IsTheHole()) { |
4823 PropertyDetails details(NONE, DATA, 0); | 4820 PropertyDetails details = PropertyDetails::Empty(); |
4824 dictionary = | 4821 dictionary = |
4825 SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details); | 4822 SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details); |
4826 } | 4823 } |
4827 } | 4824 } |
4828 return dictionary; | 4825 return dictionary; |
4829 } | 4826 } |
4830 | 4827 |
4831 | 4828 |
4832 Handle<SeededNumberDictionary> JSObject::NormalizeElements( | 4829 Handle<SeededNumberDictionary> JSObject::NormalizeElements( |
4833 Handle<JSObject> object) { | 4830 Handle<JSObject> object) { |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5287 | 5284 |
5288 | 5285 |
5289 void JSObject::DeleteNormalizedProperty(Handle<JSObject> object, | 5286 void JSObject::DeleteNormalizedProperty(Handle<JSObject> object, |
5290 Handle<Name> name) { | 5287 Handle<Name> name) { |
5291 DCHECK(!object->HasFastProperties()); | 5288 DCHECK(!object->HasFastProperties()); |
5292 Isolate* isolate = object->GetIsolate(); | 5289 Isolate* isolate = object->GetIsolate(); |
5293 Handle<NameDictionary> dictionary(object->property_dictionary()); | 5290 Handle<NameDictionary> dictionary(object->property_dictionary()); |
5294 int entry = dictionary->FindEntry(name); | 5291 int entry = dictionary->FindEntry(name); |
5295 DCHECK_NE(NameDictionary::kNotFound, entry); | 5292 DCHECK_NE(NameDictionary::kNotFound, entry); |
5296 | 5293 |
5297 // If we have a global object set the cell to the hole. | 5294 // If we have a global object, invalidate the cell and swap in a new one. |
5298 if (object->IsGlobalObject()) { | 5295 if (object->IsGlobalObject()) { |
5299 DCHECK(dictionary->DetailsAt(entry).IsConfigurable()); | 5296 auto cell = PropertyCell::InvalidateEntry(dictionary, entry); |
5300 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); | 5297 cell->set_value(isolate->heap()->the_hole_value()); |
5301 Handle<Object> value = isolate->factory()->the_hole_value(); | 5298 // TODO(dcarney): InvalidateForDelete |
5302 PropertyCell::SetValueInferType(cell, value); | 5299 dictionary->DetailsAtPut(entry, dictionary->DetailsAt(entry).set_cell_type( |
| 5300 PropertyCellType::kDeleted)); |
5303 return; | 5301 return; |
5304 } | 5302 } |
5305 | 5303 |
5306 NameDictionary::DeleteProperty(dictionary, entry); | 5304 NameDictionary::DeleteProperty(dictionary, entry); |
5307 Handle<NameDictionary> new_properties = | 5305 Handle<NameDictionary> new_properties = |
5308 NameDictionary::Shrink(dictionary, name); | 5306 NameDictionary::Shrink(dictionary, name); |
5309 object->set_properties(*new_properties); | 5307 object->set_properties(*new_properties); |
5310 } | 5308 } |
5311 | 5309 |
5312 | 5310 |
(...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6365 Object* setter, | 6363 Object* setter, |
6366 PropertyAttributes attributes) { | 6364 PropertyAttributes attributes) { |
6367 int entry = dictionary->FindEntry(index); | 6365 int entry = dictionary->FindEntry(index); |
6368 if (entry != SeededNumberDictionary::kNotFound) { | 6366 if (entry != SeededNumberDictionary::kNotFound) { |
6369 Object* result = dictionary->ValueAt(entry); | 6367 Object* result = dictionary->ValueAt(entry); |
6370 PropertyDetails details = dictionary->DetailsAt(entry); | 6368 PropertyDetails details = dictionary->DetailsAt(entry); |
6371 if (details.type() == ACCESSOR_CONSTANT && result->IsAccessorPair()) { | 6369 if (details.type() == ACCESSOR_CONSTANT && result->IsAccessorPair()) { |
6372 DCHECK(details.IsConfigurable()); | 6370 DCHECK(details.IsConfigurable()); |
6373 if (details.attributes() != attributes) { | 6371 if (details.attributes() != attributes) { |
6374 dictionary->DetailsAtPut( | 6372 dictionary->DetailsAtPut( |
6375 entry, PropertyDetails(attributes, ACCESSOR_CONSTANT, index)); | 6373 entry, PropertyDetails(attributes, ACCESSOR_CONSTANT, index, |
| 6374 PropertyCellType::kInvalid)); |
6376 } | 6375 } |
6377 AccessorPair::cast(result)->SetComponents(getter, setter); | 6376 AccessorPair::cast(result)->SetComponents(getter, setter); |
6378 return true; | 6377 return true; |
6379 } | 6378 } |
6380 } | 6379 } |
6381 return false; | 6380 return false; |
6382 } | 6381 } |
6383 | 6382 |
6384 | 6383 |
6385 void JSObject::DefineElementAccessor(Handle<JSObject> object, | 6384 void JSObject::DefineElementAccessor(Handle<JSObject> object, |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6467 | 6466 |
6468 return false; | 6467 return false; |
6469 } | 6468 } |
6470 | 6469 |
6471 | 6470 |
6472 void JSObject::SetElementCallback(Handle<JSObject> object, | 6471 void JSObject::SetElementCallback(Handle<JSObject> object, |
6473 uint32_t index, | 6472 uint32_t index, |
6474 Handle<Object> structure, | 6473 Handle<Object> structure, |
6475 PropertyAttributes attributes) { | 6474 PropertyAttributes attributes) { |
6476 Heap* heap = object->GetHeap(); | 6475 Heap* heap = object->GetHeap(); |
6477 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0); | 6476 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0, |
| 6477 PropertyCellType::kInvalid); |
6478 | 6478 |
6479 // Normalize elements to make this operation simple. | 6479 // Normalize elements to make this operation simple. |
6480 bool had_dictionary_elements = object->HasDictionaryElements(); | 6480 bool had_dictionary_elements = object->HasDictionaryElements(); |
6481 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 6481 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
6482 DCHECK(object->HasDictionaryElements() || | 6482 DCHECK(object->HasDictionaryElements() || |
6483 object->HasDictionaryArgumentsElements()); | 6483 object->HasDictionaryArgumentsElements()); |
6484 // Update the dictionary with the new ACCESSOR_CONSTANT property. | 6484 // Update the dictionary with the new ACCESSOR_CONSTANT property. |
6485 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, | 6485 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, |
6486 details); | 6486 details); |
6487 dictionary->set_requires_slow_elements(); | 6487 dictionary->set_requires_slow_elements(); |
(...skipping 24 matching lines...) Expand all Loading... |
6512 void JSObject::SetPropertyCallback(Handle<JSObject> object, | 6512 void JSObject::SetPropertyCallback(Handle<JSObject> object, |
6513 Handle<Name> name, | 6513 Handle<Name> name, |
6514 Handle<Object> structure, | 6514 Handle<Object> structure, |
6515 PropertyAttributes attributes) { | 6515 PropertyAttributes attributes) { |
6516 PropertyNormalizationMode mode = object->map()->is_prototype_map() | 6516 PropertyNormalizationMode mode = object->map()->is_prototype_map() |
6517 ? KEEP_INOBJECT_PROPERTIES | 6517 ? KEEP_INOBJECT_PROPERTIES |
6518 : CLEAR_INOBJECT_PROPERTIES; | 6518 : CLEAR_INOBJECT_PROPERTIES; |
6519 // Normalize object to make this operation simple. | 6519 // Normalize object to make this operation simple. |
6520 NormalizeProperties(object, mode, 0, "SetPropertyCallback"); | 6520 NormalizeProperties(object, mode, 0, "SetPropertyCallback"); |
6521 | 6521 |
6522 // For the global object allocate a new map to invalidate the global inline | |
6523 // caches which have a global property cell reference directly in the code. | |
6524 if (object->IsGlobalObject()) { | |
6525 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); | |
6526 DCHECK(new_map->is_dictionary_map()); | |
6527 #if TRACE_MAPS | |
6528 if (FLAG_trace_maps) { | |
6529 PrintF("[TraceMaps: GlobalPropertyCallback from= %p to= %p ]\n", | |
6530 reinterpret_cast<void*>(object->map()), | |
6531 reinterpret_cast<void*>(*new_map)); | |
6532 } | |
6533 #endif | |
6534 JSObject::MigrateToMap(object, new_map); | |
6535 | |
6536 // When running crankshaft, changing the map is not enough. We | |
6537 // need to deoptimize all functions that rely on this global | |
6538 // object. | |
6539 Deoptimizer::DeoptimizeGlobalObject(*object); | |
6540 } | |
6541 | 6522 |
6542 // Update the dictionary with the new ACCESSOR_CONSTANT property. | 6523 // Update the dictionary with the new ACCESSOR_CONSTANT property. |
6543 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0); | 6524 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0, |
| 6525 PropertyCellType::kMutable); |
6544 SetNormalizedProperty(object, name, structure, details); | 6526 SetNormalizedProperty(object, name, structure, details); |
6545 | 6527 |
6546 ReoptimizeIfPrototype(object); | 6528 ReoptimizeIfPrototype(object); |
6547 } | 6529 } |
6548 | 6530 |
6549 | 6531 |
6550 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object, | 6532 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object, |
6551 Handle<Name> name, | 6533 Handle<Name> name, |
6552 Handle<Object> getter, | 6534 Handle<Object> getter, |
6553 Handle<Object> setter, | 6535 Handle<Object> setter, |
(...skipping 6172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12726 // If a value has not been initialized we allow writing to it even if it | 12708 // If a value has not been initialized we allow writing to it even if it |
12727 // is read-only (a declared const that has not been initialized). | 12709 // is read-only (a declared const that has not been initialized). |
12728 return WriteToReadOnlyProperty( | 12710 return WriteToReadOnlyProperty( |
12729 isolate, object, isolate->factory()->NewNumberFromUint(index), | 12711 isolate, object, isolate->factory()->NewNumberFromUint(index), |
12730 isolate->factory()->undefined_value(), language_mode); | 12712 isolate->factory()->undefined_value(), language_mode); |
12731 } else { | 12713 } else { |
12732 DCHECK(details.IsConfigurable() || !details.IsReadOnly() || | 12714 DCHECK(details.IsConfigurable() || !details.IsReadOnly() || |
12733 element->IsTheHole()); | 12715 element->IsTheHole()); |
12734 dictionary->UpdateMaxNumberKey(index); | 12716 dictionary->UpdateMaxNumberKey(index); |
12735 if (set_mode == DEFINE_PROPERTY) { | 12717 if (set_mode == DEFINE_PROPERTY) { |
12736 details = PropertyDetails(attributes, DATA, details.dictionary_index()); | 12718 details = PropertyDetails(attributes, DATA, details.dictionary_index(), |
| 12719 PropertyCellType::kInvalid); |
12737 dictionary->DetailsAtPut(entry, details); | 12720 dictionary->DetailsAtPut(entry, details); |
12738 } | 12721 } |
12739 | 12722 |
12740 // Elements of the arguments object in slow mode might be slow aliases. | 12723 // Elements of the arguments object in slow mode might be slow aliases. |
12741 if (is_arguments && element->IsAliasedArgumentsEntry()) { | 12724 if (is_arguments && element->IsAliasedArgumentsEntry()) { |
12742 Handle<AliasedArgumentsEntry> entry = | 12725 Handle<AliasedArgumentsEntry> entry = |
12743 Handle<AliasedArgumentsEntry>::cast(element); | 12726 Handle<AliasedArgumentsEntry>::cast(element); |
12744 Handle<Context> context(Context::cast(elements->get(0))); | 12727 Handle<Context> context(Context::cast(elements->get(0))); |
12745 int context_index = entry->aliased_context_slot(); | 12728 int context_index = entry->aliased_context_slot(); |
12746 DCHECK(!context->get(context_index)->IsTheHole()); | 12729 DCHECK(!context->get(context_index)->IsTheHole()); |
(...skipping 22 matching lines...) Expand all Loading... |
12769 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12752 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
12770 Handle<String> name = isolate->factory()->NumberToString(number); | 12753 Handle<String> name = isolate->factory()->NumberToString(number); |
12771 Handle<Object> args[] = {name}; | 12754 Handle<Object> args[] = {name}; |
12772 THROW_NEW_ERROR(isolate, | 12755 THROW_NEW_ERROR(isolate, |
12773 NewTypeError("object_not_extensible", | 12756 NewTypeError("object_not_extensible", |
12774 HandleVector(args, arraysize(args))), | 12757 HandleVector(args, arraysize(args))), |
12775 Object); | 12758 Object); |
12776 } | 12759 } |
12777 } | 12760 } |
12778 | 12761 |
12779 PropertyDetails details(attributes, DATA, 0); | 12762 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kInvalid); |
12780 Handle<SeededNumberDictionary> new_dictionary = | 12763 Handle<SeededNumberDictionary> new_dictionary = |
12781 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, | 12764 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, |
12782 details); | 12765 details); |
12783 if (*dictionary != *new_dictionary) { | 12766 if (*dictionary != *new_dictionary) { |
12784 if (is_arguments) { | 12767 if (is_arguments) { |
12785 elements->set(1, *new_dictionary); | 12768 elements->set(1, *new_dictionary); |
12786 } else { | 12769 } else { |
12787 object->set_elements(*new_dictionary); | 12770 object->set_elements(*new_dictionary); |
12788 } | 12771 } |
12789 dictionary = new_dictionary; | 12772 dictionary = new_dictionary; |
(...skipping 2064 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14854 return bailout; | 14837 return bailout; |
14855 } else { | 14838 } else { |
14856 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( | 14839 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( |
14857 new_dict, key, value, details); | 14840 new_dict, key, value, details); |
14858 DCHECK(result.is_identical_to(new_dict)); | 14841 DCHECK(result.is_identical_to(new_dict)); |
14859 USE(result); | 14842 USE(result); |
14860 } | 14843 } |
14861 } | 14844 } |
14862 | 14845 |
14863 uint32_t result = pos; | 14846 uint32_t result = pos; |
14864 PropertyDetails no_details(NONE, DATA, 0); | 14847 PropertyDetails no_details = PropertyDetails::Empty(); |
14865 while (undefs > 0) { | 14848 while (undefs > 0) { |
14866 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { | 14849 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { |
14867 // Adding an entry with the key beyond smi-range requires | 14850 // Adding an entry with the key beyond smi-range requires |
14868 // allocation. Bailout. | 14851 // allocation. Bailout. |
14869 return bailout; | 14852 return bailout; |
14870 } | 14853 } |
14871 HandleScope scope(isolate); | 14854 HandleScope scope(isolate); |
14872 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( | 14855 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( |
14873 new_dict, pos, isolate->factory()->undefined_value(), no_details); | 14856 new_dict, pos, isolate->factory()->undefined_value(), no_details); |
14874 DCHECK(result.is_identical_to(new_dict)); | 14857 DCHECK(result.is_identical_to(new_dict)); |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15215 } | 15198 } |
15216 array->set(index, double_value); | 15199 array->set(index, double_value); |
15217 } | 15200 } |
15218 return array->GetIsolate()->factory()->NewNumber(double_value); | 15201 return array->GetIsolate()->factory()->NewNumber(double_value); |
15219 } | 15202 } |
15220 | 15203 |
15221 | 15204 |
15222 void GlobalObject::InvalidatePropertyCell(Handle<GlobalObject> global, | 15205 void GlobalObject::InvalidatePropertyCell(Handle<GlobalObject> global, |
15223 Handle<Name> name) { | 15206 Handle<Name> name) { |
15224 DCHECK(!global->HasFastProperties()); | 15207 DCHECK(!global->HasFastProperties()); |
15225 Isolate* isolate = global->GetIsolate(); | 15208 auto dictionary = handle(global->property_dictionary()); |
15226 int entry = global->property_dictionary()->FindEntry(name); | 15209 int entry = dictionary->FindEntry(name); |
15227 if (entry != NameDictionary::kNotFound) { | 15210 if (entry == NameDictionary::kNotFound) return; |
15228 Handle<PropertyCell> cell( | 15211 PropertyCell::InvalidateEntry(dictionary, entry); |
15229 PropertyCell::cast(global->property_dictionary()->ValueAt(entry))); | |
15230 | |
15231 Handle<Object> value(cell->value(), isolate); | |
15232 Handle<PropertyCell> new_cell = isolate->factory()->NewPropertyCell(value); | |
15233 global->property_dictionary()->ValueAtPut(entry, *new_cell); | |
15234 | |
15235 Handle<Object> hole = isolate->factory()->the_hole_value(); | |
15236 if (*hole != *value) { | |
15237 PropertyCell::SetValueInferType(cell, hole); | |
15238 } else { | |
15239 // If property value was the hole, set it to any other value, | |
15240 // to ensure that LoadNonexistent ICs execute a miss. | |
15241 Handle<Object> undefined = isolate->factory()->undefined_value(); | |
15242 PropertyCell::SetValueInferType(cell, undefined); | |
15243 } | |
15244 } | |
15245 } | 15212 } |
15246 | 15213 |
15247 | 15214 |
| 15215 // TODO(dcarney): rename to EnsureEmptyPropertyCell or something. |
15248 Handle<PropertyCell> GlobalObject::EnsurePropertyCell( | 15216 Handle<PropertyCell> GlobalObject::EnsurePropertyCell( |
15249 Handle<GlobalObject> global, Handle<Name> name) { | 15217 Handle<GlobalObject> global, Handle<Name> name) { |
15250 DCHECK(!global->HasFastProperties()); | 15218 DCHECK(!global->HasFastProperties()); |
15251 int entry = global->property_dictionary()->FindEntry(name); | 15219 auto dictionary = handle(global->property_dictionary()); |
15252 if (entry == NameDictionary::kNotFound) { | 15220 int entry = dictionary->FindEntry(name); |
15253 Isolate* isolate = global->GetIsolate(); | 15221 Handle<PropertyCell> cell; |
15254 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCellWithHole(); | 15222 if (entry != NameDictionary::kNotFound) { |
15255 PropertyDetails details(NONE, DATA, 0); | 15223 // This call should be idempotent. |
15256 Handle<NameDictionary> dictionary = NameDictionary::Add( | 15224 DCHECK(dictionary->DetailsAt(entry).cell_type() == |
15257 handle(global->property_dictionary()), name, cell, details); | 15225 PropertyCellType::kUninitialized || |
15258 global->set_properties(*dictionary); | 15226 dictionary->DetailsAt(entry).cell_type() == |
| 15227 PropertyCellType::kDeleted); |
| 15228 cell = handle(PropertyCell::cast(dictionary->ValueAt(entry))); |
| 15229 DCHECK(cell->value()->IsTheHole()); |
15259 return cell; | 15230 return cell; |
15260 } else { | |
15261 Object* value = global->property_dictionary()->ValueAt(entry); | |
15262 DCHECK(value->IsPropertyCell()); | |
15263 return handle(PropertyCell::cast(value)); | |
15264 } | 15231 } |
| 15232 Isolate* isolate = global->GetIsolate(); |
| 15233 cell = isolate->factory()->NewPropertyCell(); |
| 15234 PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized); |
| 15235 dictionary = NameDictionary::Add(dictionary, name, cell, details); |
| 15236 global->set_properties(*dictionary); |
| 15237 return cell; |
15265 } | 15238 } |
15266 | 15239 |
15267 | 15240 |
15268 // This class is used for looking up two character strings in the string table. | 15241 // This class is used for looking up two character strings in the string table. |
15269 // If we don't have a hit we don't want to waste much time so we unroll the | 15242 // If we don't have a hit we don't want to waste much time so we unroll the |
15270 // string hash calculation loop here for speed. Doesn't work if the two | 15243 // string hash calculation loop here for speed. Doesn't work if the two |
15271 // characters form a decimal integer, since such strings have a different hash | 15244 // characters form a decimal integer, since such strings have a different hash |
15272 // algorithm. | 15245 // algorithm. |
15273 class TwoCharHashTableKey : public HashTableKey { | 15246 class TwoCharHashTableKey : public HashTableKey { |
15274 public: | 15247 public: |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15664 | 15637 |
15665 // Iterate over the dictionary using the enumeration order and update | 15638 // Iterate over the dictionary using the enumeration order and update |
15666 // the dictionary with new enumeration indices. | 15639 // the dictionary with new enumeration indices. |
15667 for (int i = 0; i < length; i++) { | 15640 for (int i = 0; i < length; i++) { |
15668 int index = Smi::cast(iteration_order->get(i))->value(); | 15641 int index = Smi::cast(iteration_order->get(i))->value(); |
15669 DCHECK(dictionary->IsKey(dictionary->KeyAt(index))); | 15642 DCHECK(dictionary->IsKey(dictionary->KeyAt(index))); |
15670 | 15643 |
15671 int enum_index = PropertyDetails::kInitialIndex + i; | 15644 int enum_index = PropertyDetails::kInitialIndex + i; |
15672 | 15645 |
15673 PropertyDetails details = dictionary->DetailsAt(index); | 15646 PropertyDetails details = dictionary->DetailsAt(index); |
15674 PropertyDetails new_details = | 15647 PropertyDetails new_details = details.set_index(enum_index); |
15675 PropertyDetails(details.attributes(), details.type(), enum_index); | |
15676 dictionary->DetailsAtPut(index, new_details); | 15648 dictionary->DetailsAtPut(index, new_details); |
15677 } | 15649 } |
15678 | 15650 |
15679 // Set the next enumeration index. | 15651 // Set the next enumeration index. |
15680 dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length); | 15652 dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length); |
15681 return iteration_order; | 15653 return iteration_order; |
15682 } | 15654 } |
15683 | 15655 |
15684 | 15656 |
15685 template<typename Derived, typename Shape, typename Key> | 15657 template<typename Derived, typename Shape, typename Key> |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15718 if (entry != Dictionary::kNotFound) { | 15690 if (entry != Dictionary::kNotFound) { |
15719 dictionary->ValueAtPut(entry, *value); | 15691 dictionary->ValueAtPut(entry, *value); |
15720 return dictionary; | 15692 return dictionary; |
15721 } | 15693 } |
15722 | 15694 |
15723 // Check whether the dictionary should be extended. | 15695 // Check whether the dictionary should be extended. |
15724 dictionary = EnsureCapacity(dictionary, 1, key); | 15696 dictionary = EnsureCapacity(dictionary, 1, key); |
15725 #ifdef DEBUG | 15697 #ifdef DEBUG |
15726 USE(Shape::AsHandle(dictionary->GetIsolate(), key)); | 15698 USE(Shape::AsHandle(dictionary->GetIsolate(), key)); |
15727 #endif | 15699 #endif |
15728 PropertyDetails details(NONE, DATA, 0); | 15700 PropertyDetails details = PropertyDetails::Empty(); |
15729 | 15701 |
15730 AddEntry(dictionary, key, value, details, dictionary->Hash(key)); | 15702 AddEntry(dictionary, key, value, details, dictionary->Hash(key)); |
15731 return dictionary; | 15703 return dictionary; |
15732 } | 15704 } |
15733 | 15705 |
15734 | 15706 |
15735 template<typename Derived, typename Shape, typename Key> | 15707 template<typename Derived, typename Shape, typename Key> |
15736 Handle<Derived> Dictionary<Derived, Shape, Key>::Add( | 15708 Handle<Derived> Dictionary<Derived, Shape, Key>::Add( |
15737 Handle<Derived> dictionary, | 15709 Handle<Derived> dictionary, |
15738 Key key, | 15710 Key key, |
(...skipping 19 matching lines...) Expand all Loading... |
15758 uint32_t hash) { | 15730 uint32_t hash) { |
15759 // Compute the key object. | 15731 // Compute the key object. |
15760 Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key); | 15732 Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key); |
15761 | 15733 |
15762 uint32_t entry = dictionary->FindInsertionEntry(hash); | 15734 uint32_t entry = dictionary->FindInsertionEntry(hash); |
15763 // Insert element at empty or deleted entry | 15735 // Insert element at empty or deleted entry |
15764 if (details.dictionary_index() == 0 && Shape::kIsEnumerable) { | 15736 if (details.dictionary_index() == 0 && Shape::kIsEnumerable) { |
15765 // Assign an enumeration index to the property and update | 15737 // Assign an enumeration index to the property and update |
15766 // SetNextEnumerationIndex. | 15738 // SetNextEnumerationIndex. |
15767 int index = dictionary->NextEnumerationIndex(); | 15739 int index = dictionary->NextEnumerationIndex(); |
15768 details = PropertyDetails(details.attributes(), details.type(), index); | 15740 details = details.set_index(index); |
15769 dictionary->SetNextEnumerationIndex(index + 1); | 15741 dictionary->SetNextEnumerationIndex(index + 1); |
15770 } | 15742 } |
15771 dictionary->SetEntry(entry, k, value, details); | 15743 dictionary->SetEntry(entry, k, value, details); |
15772 DCHECK((dictionary->KeyAt(entry)->IsNumber() || | 15744 DCHECK((dictionary->KeyAt(entry)->IsNumber() || |
15773 dictionary->KeyAt(entry)->IsName())); | 15745 dictionary->KeyAt(entry)->IsName())); |
15774 dictionary->ElementAdded(); | 15746 dictionary->ElementAdded(); |
15775 } | 15747 } |
15776 | 15748 |
15777 | 15749 |
15778 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) { | 15750 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) { |
(...skipping 25 matching lines...) Expand all Loading... |
15804 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); | 15776 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); |
15805 return Add(dictionary, key, value, details); | 15777 return Add(dictionary, key, value, details); |
15806 } | 15778 } |
15807 | 15779 |
15808 | 15780 |
15809 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry( | 15781 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry( |
15810 Handle<UnseededNumberDictionary> dictionary, | 15782 Handle<UnseededNumberDictionary> dictionary, |
15811 uint32_t key, | 15783 uint32_t key, |
15812 Handle<Object> value) { | 15784 Handle<Object> value) { |
15813 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); | 15785 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); |
15814 return Add(dictionary, key, value, PropertyDetails(NONE, DATA, 0)); | 15786 return Add(dictionary, key, value, PropertyDetails::Empty()); |
15815 } | 15787 } |
15816 | 15788 |
15817 | 15789 |
15818 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut( | 15790 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut( |
15819 Handle<SeededNumberDictionary> dictionary, | 15791 Handle<SeededNumberDictionary> dictionary, |
15820 uint32_t key, | 15792 uint32_t key, |
15821 Handle<Object> value) { | 15793 Handle<Object> value) { |
15822 dictionary->UpdateMaxNumberKey(key); | 15794 dictionary->UpdateMaxNumberKey(key); |
15823 return AtPut(dictionary, key, value); | 15795 return AtPut(dictionary, key, value); |
15824 } | 15796 } |
(...skipping 10 matching lines...) Expand all Loading... |
15835 Handle<SeededNumberDictionary> SeededNumberDictionary::Set( | 15807 Handle<SeededNumberDictionary> SeededNumberDictionary::Set( |
15836 Handle<SeededNumberDictionary> dictionary, | 15808 Handle<SeededNumberDictionary> dictionary, |
15837 uint32_t key, | 15809 uint32_t key, |
15838 Handle<Object> value, | 15810 Handle<Object> value, |
15839 PropertyDetails details) { | 15811 PropertyDetails details) { |
15840 int entry = dictionary->FindEntry(key); | 15812 int entry = dictionary->FindEntry(key); |
15841 if (entry == kNotFound) { | 15813 if (entry == kNotFound) { |
15842 return AddNumberEntry(dictionary, key, value, details); | 15814 return AddNumberEntry(dictionary, key, value, details); |
15843 } | 15815 } |
15844 // Preserve enumeration index. | 15816 // Preserve enumeration index. |
15845 details = PropertyDetails(details.attributes(), | 15817 details = details.set_index(dictionary->DetailsAt(entry).dictionary_index()); |
15846 details.type(), | |
15847 dictionary->DetailsAt(entry).dictionary_index()); | |
15848 Handle<Object> object_key = | 15818 Handle<Object> object_key = |
15849 SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key); | 15819 SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key); |
15850 dictionary->SetEntry(entry, object_key, value, details); | 15820 dictionary->SetEntry(entry, object_key, value, details); |
15851 return dictionary; | 15821 return dictionary; |
15852 } | 15822 } |
15853 | 15823 |
15854 | 15824 |
15855 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set( | 15825 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set( |
15856 Handle<UnseededNumberDictionary> dictionary, | 15826 Handle<UnseededNumberDictionary> dictionary, |
15857 uint32_t key, | 15827 uint32_t key, |
(...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17015 Handle<Object> result(buffer(), GetIsolate()); | 16985 Handle<Object> result(buffer(), GetIsolate()); |
17016 if (*result != Smi::FromInt(0)) { | 16986 if (*result != Smi::FromInt(0)) { |
17017 DCHECK(IsExternalArrayElementsKind(map()->elements_kind())); | 16987 DCHECK(IsExternalArrayElementsKind(map()->elements_kind())); |
17018 return Handle<JSArrayBuffer>::cast(result); | 16988 return Handle<JSArrayBuffer>::cast(result); |
17019 } | 16989 } |
17020 Handle<JSTypedArray> self(this); | 16990 Handle<JSTypedArray> self(this); |
17021 return MaterializeArrayBuffer(self); | 16991 return MaterializeArrayBuffer(self); |
17022 } | 16992 } |
17023 | 16993 |
17024 | 16994 |
17025 HeapType* PropertyCell::type() { | 16995 Handle<PropertyCell> PropertyCell::InvalidateEntry( |
17026 return static_cast<HeapType*>(type_raw()); | 16996 Handle<NameDictionary> dictionary, int entry) { |
| 16997 Isolate* isolate = dictionary->GetIsolate(); |
| 16998 // Swap with a copy. |
| 16999 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
| 17000 auto new_cell = isolate->factory()->NewPropertyCell(); |
| 17001 new_cell->set_value(cell->value()); |
| 17002 dictionary->ValueAtPut(entry, *new_cell); |
| 17003 bool is_the_hole = cell->value()->IsTheHole(); |
| 17004 // Cell is officially mutable henceforth. |
| 17005 auto details = dictionary->DetailsAt(entry); |
| 17006 details = details.set_cell_type(is_the_hole ? PropertyCellType::kDeleted |
| 17007 : PropertyCellType::kMutable); |
| 17008 dictionary->DetailsAtPut(entry, details); |
| 17009 // Old cell is ready for invalidation. |
| 17010 if (is_the_hole) { |
| 17011 cell->set_value(isolate->heap()->undefined_value()); |
| 17012 } else { |
| 17013 cell->set_value(isolate->heap()->the_hole_value()); |
| 17014 } |
| 17015 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 17016 isolate, DependentCode::kPropertyCellChangedGroup); |
| 17017 return new_cell; |
17027 } | 17018 } |
17028 | 17019 |
17029 | 17020 |
17030 void PropertyCell::set_type(HeapType* type, WriteBarrierMode ignored) { | 17021 PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell, |
17031 DCHECK(IsPropertyCell()); | 17022 Handle<Object> value, |
17032 set_type_raw(type, ignored); | 17023 PropertyDetails details) { |
| 17024 PropertyCellType type = details.cell_type(); |
| 17025 DCHECK(!value->IsTheHole()); |
| 17026 DCHECK_IMPLIES(cell->value()->IsTheHole(), |
| 17027 type == PropertyCellType::kUninitialized || |
| 17028 type == PropertyCellType::kDeleted); |
| 17029 switch (type) { |
| 17030 // Only allow a cell to transition once into constant state. |
| 17031 case PropertyCellType::kUninitialized: |
| 17032 if (value->IsUndefined()) return PropertyCellType::kUndefined; |
| 17033 return PropertyCellType::kConstant; |
| 17034 case PropertyCellType::kUndefined: |
| 17035 return PropertyCellType::kConstant; |
| 17036 case PropertyCellType::kConstant: |
| 17037 // No transition. |
| 17038 if (*value == cell->value()) return PropertyCellType::kConstant; |
| 17039 // Fall through. |
| 17040 case PropertyCellType::kMutable: |
| 17041 return PropertyCellType::kMutable; |
| 17042 } |
| 17043 UNREACHABLE(); |
| 17044 return PropertyCellType::kMutable; |
17033 } | 17045 } |
17034 | 17046 |
17035 | 17047 |
17036 Handle<HeapType> PropertyCell::UpdatedType(Handle<PropertyCell> cell, | 17048 Handle<Object> PropertyCell::UpdateCell(Handle<NameDictionary> dictionary, |
17037 Handle<Object> value) { | 17049 int entry, Handle<Object> value, |
17038 Isolate* isolate = cell->GetIsolate(); | 17050 PropertyDetails details) { |
17039 Handle<HeapType> old_type(cell->type(), isolate); | 17051 DCHECK(!value->IsTheHole()); |
17040 Handle<HeapType> new_type = HeapType::Constant(value, isolate); | 17052 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
| 17053 const PropertyDetails original_details = dictionary->DetailsAt(entry); |
| 17054 // Data accesses could be cached in ics or optimized code. |
| 17055 bool invalidate = |
| 17056 original_details.kind() == kData && details.kind() == kAccessor; |
| 17057 int index = original_details.dictionary_index(); |
| 17058 auto old_type = original_details.cell_type(); |
| 17059 // Preserve the enumeration index unless the property was deleted or never |
| 17060 // initialized. |
| 17061 if (cell->value()->IsTheHole()) { |
| 17062 index = dictionary->NextEnumerationIndex(); |
| 17063 dictionary->SetNextEnumerationIndex(index + 1); |
| 17064 // Negative lookup cells must be invalidated. |
| 17065 invalidate = true; |
| 17066 } |
| 17067 DCHECK(index > 0); |
| 17068 details = details.set_index(index); |
17041 | 17069 |
17042 if (new_type->Is(old_type)) return old_type; | |
17043 | |
17044 cell->dependent_code()->DeoptimizeDependentCodeGroup( | |
17045 isolate, DependentCode::kPropertyCellChangedGroup); | |
17046 | |
17047 if (old_type->Is(HeapType::None()) || old_type->Is(HeapType::Undefined())) { | |
17048 return new_type; | |
17049 } | |
17050 | |
17051 return HeapType::Any(isolate); | |
17052 } | |
17053 | |
17054 | |
17055 Handle<Object> PropertyCell::SetValueInferType(Handle<PropertyCell> cell, | |
17056 Handle<Object> value) { | |
17057 // Heuristic: if a small-ish string is stored in a previously uninitialized | 17070 // Heuristic: if a small-ish string is stored in a previously uninitialized |
17058 // property cell, internalize it. | 17071 // property cell, internalize it. |
17059 const int kMaxLengthForInternalization = 200; | 17072 const int kMaxLengthForInternalization = 200; |
17060 if ((cell->type()->Is(HeapType::None()) || | 17073 if ((old_type == PropertyCellType::kUninitialized || |
17061 cell->type()->Is(HeapType::Undefined())) && | 17074 old_type == PropertyCellType::kUndefined) && |
17062 value->IsString()) { | 17075 value->IsString()) { |
17063 auto string = Handle<String>::cast(value); | 17076 auto string = Handle<String>::cast(value); |
17064 if (string->length() <= kMaxLengthForInternalization && | 17077 if (string->length() <= kMaxLengthForInternalization) { |
17065 !string->map()->is_undetectable()) { | |
17066 value = cell->GetIsolate()->factory()->InternalizeString(string); | 17078 value = cell->GetIsolate()->factory()->InternalizeString(string); |
17067 } | 17079 } |
17068 } | 17080 } |
| 17081 |
| 17082 auto new_type = UpdatedType(cell, value, original_details); |
| 17083 if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry); |
| 17084 |
| 17085 // Install new property details and cell value. |
| 17086 details = details.set_cell_type(new_type); |
| 17087 dictionary->DetailsAtPut(entry, details); |
17069 cell->set_value(*value); | 17088 cell->set_value(*value); |
17070 if (!HeapType::Any()->Is(cell->type())) { | 17089 |
17071 Handle<HeapType> new_type = UpdatedType(cell, value); | 17090 // Deopt when transitioning from a constant type. |
17072 cell->set_type(*new_type); | 17091 if (!invalidate && old_type == PropertyCellType::kConstant && |
| 17092 new_type != PropertyCellType::kConstant) { |
| 17093 auto isolate = dictionary->GetIsolate(); |
| 17094 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 17095 isolate, DependentCode::kPropertyCellChangedGroup); |
17073 } | 17096 } |
17074 return value; | 17097 return value; |
17075 } | 17098 } |
17076 | 17099 |
17077 | 17100 |
17078 // static | 17101 // static |
17079 void PropertyCell::AddDependentCompilationInfo(Handle<PropertyCell> cell, | 17102 void PropertyCell::AddDependentCompilationInfo(Handle<PropertyCell> cell, |
17080 CompilationInfo* info) { | 17103 CompilationInfo* info) { |
17081 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( | 17104 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( |
17082 handle(cell->dependent_code(), info->isolate()), | 17105 handle(cell->dependent_code(), info->isolate()), |
17083 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); | 17106 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); |
17084 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 17107 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
17085 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 17108 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
17086 cell, info->zone()); | 17109 cell, info->zone()); |
17087 } | 17110 } |
17088 | 17111 |
17089 } } // namespace v8::internal | 17112 } } // namespace v8::internal |
OLD | NEW |