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