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 1767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1778 } | 1778 } |
1779 | 1779 |
1780 | 1780 |
1781 void JSObject::AddSlowProperty(Handle<JSObject> object, | 1781 void JSObject::AddSlowProperty(Handle<JSObject> object, |
1782 Handle<Name> name, | 1782 Handle<Name> name, |
1783 Handle<Object> value, | 1783 Handle<Object> value, |
1784 PropertyAttributes attributes) { | 1784 PropertyAttributes attributes) { |
1785 DCHECK(!object->HasFastProperties()); | 1785 DCHECK(!object->HasFastProperties()); |
1786 Isolate* isolate = object->GetIsolate(); | 1786 Isolate* isolate = object->GetIsolate(); |
1787 Handle<NameDictionary> dict(object->property_dictionary()); | 1787 Handle<NameDictionary> dict(object->property_dictionary()); |
1788 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kInvalid); | 1788 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
1789 if (object->IsGlobalObject()) { | 1789 if (object->IsGlobalObject()) { |
1790 int entry = dict->FindEntry(name); | 1790 int entry = dict->FindEntry(name); |
1791 // If there's a cell there, just invalidate and set the property. | 1791 // If there's a cell there, just invalidate and set the property. |
1792 if (entry != NameDictionary::kNotFound) { | 1792 if (entry != NameDictionary::kNotFound) { |
1793 PropertyCell::UpdateCell(dict, entry, value, details); | 1793 PropertyCell::UpdateCell(dict, entry, value, details); |
1794 // TODO(dcarney): move this to UpdateCell. | 1794 // TODO(dcarney): move this to UpdateCell. |
1795 // Need to adjust the details. | 1795 // Need to adjust the details. |
1796 int index = dict->NextEnumerationIndex(); | 1796 int index = dict->NextEnumerationIndex(); |
1797 dict->SetNextEnumerationIndex(index + 1); | 1797 dict->SetNextEnumerationIndex(index + 1); |
1798 details = dict->DetailsAt(entry).set_index(index); | 1798 details = dict->DetailsAt(entry).set_index(index); |
(...skipping 2782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4581 NameDictionary::New(isolate, property_count); | 4581 NameDictionary::New(isolate, property_count); |
4582 | 4582 |
4583 Handle<DescriptorArray> descs(map->instance_descriptors()); | 4583 Handle<DescriptorArray> descs(map->instance_descriptors()); |
4584 for (int i = 0; i < real_size; i++) { | 4584 for (int i = 0; i < real_size; i++) { |
4585 PropertyDetails details = descs->GetDetails(i); | 4585 PropertyDetails details = descs->GetDetails(i); |
4586 Handle<Name> key(descs->GetKey(i)); | 4586 Handle<Name> key(descs->GetKey(i)); |
4587 switch (details.type()) { | 4587 switch (details.type()) { |
4588 case DATA_CONSTANT: { | 4588 case DATA_CONSTANT: { |
4589 Handle<Object> value(descs->GetConstant(i), isolate); | 4589 Handle<Object> value(descs->GetConstant(i), isolate); |
4590 PropertyDetails d(details.attributes(), DATA, i + 1, | 4590 PropertyDetails d(details.attributes(), DATA, i + 1, |
4591 PropertyCellType::kInvalid); | 4591 PropertyCellType::kNoCell); |
4592 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4592 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4593 break; | 4593 break; |
4594 } | 4594 } |
4595 case DATA: { | 4595 case DATA: { |
4596 FieldIndex index = FieldIndex::ForDescriptor(*map, i); | 4596 FieldIndex index = FieldIndex::ForDescriptor(*map, i); |
4597 Handle<Object> value; | 4597 Handle<Object> value; |
4598 if (object->IsUnboxedDoubleField(index)) { | 4598 if (object->IsUnboxedDoubleField(index)) { |
4599 double old_value = object->RawFastDoublePropertyAt(index); | 4599 double old_value = object->RawFastDoublePropertyAt(index); |
4600 value = isolate->factory()->NewHeapNumber(old_value); | 4600 value = isolate->factory()->NewHeapNumber(old_value); |
4601 } else { | 4601 } else { |
4602 value = handle(object->RawFastPropertyAt(index), isolate); | 4602 value = handle(object->RawFastPropertyAt(index), isolate); |
4603 if (details.representation().IsDouble()) { | 4603 if (details.representation().IsDouble()) { |
4604 DCHECK(value->IsMutableHeapNumber()); | 4604 DCHECK(value->IsMutableHeapNumber()); |
4605 Handle<HeapNumber> old = Handle<HeapNumber>::cast(value); | 4605 Handle<HeapNumber> old = Handle<HeapNumber>::cast(value); |
4606 value = isolate->factory()->NewHeapNumber(old->value()); | 4606 value = isolate->factory()->NewHeapNumber(old->value()); |
4607 } | 4607 } |
4608 } | 4608 } |
4609 PropertyDetails d(details.attributes(), DATA, i + 1, | 4609 PropertyDetails d(details.attributes(), DATA, i + 1, |
4610 PropertyCellType::kInvalid); | 4610 PropertyCellType::kNoCell); |
4611 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4611 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4612 break; | 4612 break; |
4613 } | 4613 } |
4614 case ACCESSOR: { | 4614 case ACCESSOR: { |
4615 FieldIndex index = FieldIndex::ForDescriptor(*map, i); | 4615 FieldIndex index = FieldIndex::ForDescriptor(*map, i); |
4616 Handle<Object> value(object->RawFastPropertyAt(index), isolate); | 4616 Handle<Object> value(object->RawFastPropertyAt(index), isolate); |
4617 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, | 4617 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, |
4618 PropertyCellType::kInvalid); | 4618 PropertyCellType::kNoCell); |
4619 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4619 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4620 break; | 4620 break; |
4621 } | 4621 } |
4622 case ACCESSOR_CONSTANT: { | 4622 case ACCESSOR_CONSTANT: { |
4623 Handle<Object> value(descs->GetCallbacksObject(i), isolate); | 4623 Handle<Object> value(descs->GetCallbacksObject(i), isolate); |
4624 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, | 4624 PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1, |
4625 PropertyCellType::kInvalid); | 4625 PropertyCellType::kNoCell); |
4626 dictionary = NameDictionary::Add(dictionary, key, value, d); | 4626 dictionary = NameDictionary::Add(dictionary, key, value, d); |
4627 break; | 4627 break; |
4628 } | 4628 } |
4629 } | 4629 } |
4630 } | 4630 } |
4631 | 4631 |
4632 // Copy the next enumeration index from instance descriptor. | 4632 // Copy the next enumeration index from instance descriptor. |
4633 dictionary->SetNextEnumerationIndex(real_size + 1); | 4633 dictionary->SetNextEnumerationIndex(real_size + 1); |
4634 | 4634 |
4635 // From here on we cannot fail and we shouldn't GC anymore. | 4635 // From here on we cannot fail and we shouldn't GC anymore. |
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5334 Handle<NameDictionary> dictionary(object->property_dictionary()); | 5334 Handle<NameDictionary> dictionary(object->property_dictionary()); |
5335 int entry = dictionary->FindEntry(name); | 5335 int entry = dictionary->FindEntry(name); |
5336 DCHECK_NE(NameDictionary::kNotFound, entry); | 5336 DCHECK_NE(NameDictionary::kNotFound, entry); |
5337 | 5337 |
5338 // If we have a global object, invalidate the cell and swap in a new one. | 5338 // If we have a global object, invalidate the cell and swap in a new one. |
5339 if (object->IsGlobalObject()) { | 5339 if (object->IsGlobalObject()) { |
5340 auto cell = PropertyCell::InvalidateEntry(dictionary, entry); | 5340 auto cell = PropertyCell::InvalidateEntry(dictionary, entry); |
5341 cell->set_value(isolate->heap()->the_hole_value()); | 5341 cell->set_value(isolate->heap()->the_hole_value()); |
5342 // TODO(dcarney): InvalidateForDelete | 5342 // TODO(dcarney): InvalidateForDelete |
5343 dictionary->DetailsAtPut(entry, dictionary->DetailsAt(entry).set_cell_type( | 5343 dictionary->DetailsAtPut(entry, dictionary->DetailsAt(entry).set_cell_type( |
5344 PropertyCellType::kDeleted)); | 5344 PropertyCellType::kInvalidated)); |
5345 return; | 5345 return; |
5346 } | 5346 } |
5347 | 5347 |
5348 NameDictionary::DeleteProperty(dictionary, entry); | 5348 NameDictionary::DeleteProperty(dictionary, entry); |
5349 Handle<NameDictionary> new_properties = | 5349 Handle<NameDictionary> new_properties = |
5350 NameDictionary::Shrink(dictionary, name); | 5350 NameDictionary::Shrink(dictionary, name); |
5351 object->set_properties(*new_properties); | 5351 object->set_properties(*new_properties); |
5352 } | 5352 } |
5353 | 5353 |
5354 | 5354 |
(...skipping 1053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6408 PropertyAttributes attributes) { | 6408 PropertyAttributes attributes) { |
6409 int entry = dictionary->FindEntry(index); | 6409 int entry = dictionary->FindEntry(index); |
6410 if (entry != SeededNumberDictionary::kNotFound) { | 6410 if (entry != SeededNumberDictionary::kNotFound) { |
6411 Object* result = dictionary->ValueAt(entry); | 6411 Object* result = dictionary->ValueAt(entry); |
6412 PropertyDetails details = dictionary->DetailsAt(entry); | 6412 PropertyDetails details = dictionary->DetailsAt(entry); |
6413 if (details.type() == ACCESSOR_CONSTANT && result->IsAccessorPair()) { | 6413 if (details.type() == ACCESSOR_CONSTANT && result->IsAccessorPair()) { |
6414 DCHECK(details.IsConfigurable()); | 6414 DCHECK(details.IsConfigurable()); |
6415 if (details.attributes() != attributes) { | 6415 if (details.attributes() != attributes) { |
6416 dictionary->DetailsAtPut( | 6416 dictionary->DetailsAtPut( |
6417 entry, PropertyDetails(attributes, ACCESSOR_CONSTANT, index, | 6417 entry, PropertyDetails(attributes, ACCESSOR_CONSTANT, index, |
6418 PropertyCellType::kInvalid)); | 6418 PropertyCellType::kNoCell)); |
6419 } | 6419 } |
6420 AccessorPair::cast(result)->SetComponents(getter, setter); | 6420 AccessorPair::cast(result)->SetComponents(getter, setter); |
6421 return true; | 6421 return true; |
6422 } | 6422 } |
6423 } | 6423 } |
6424 return false; | 6424 return false; |
6425 } | 6425 } |
6426 | 6426 |
6427 | 6427 |
6428 void JSObject::DefineElementAccessor(Handle<JSObject> object, | 6428 void JSObject::DefineElementAccessor(Handle<JSObject> object, |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6511 return false; | 6511 return false; |
6512 } | 6512 } |
6513 | 6513 |
6514 | 6514 |
6515 void JSObject::SetElementCallback(Handle<JSObject> object, | 6515 void JSObject::SetElementCallback(Handle<JSObject> object, |
6516 uint32_t index, | 6516 uint32_t index, |
6517 Handle<Object> structure, | 6517 Handle<Object> structure, |
6518 PropertyAttributes attributes) { | 6518 PropertyAttributes attributes) { |
6519 Heap* heap = object->GetHeap(); | 6519 Heap* heap = object->GetHeap(); |
6520 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0, | 6520 PropertyDetails details = PropertyDetails(attributes, ACCESSOR_CONSTANT, 0, |
6521 PropertyCellType::kInvalid); | 6521 PropertyCellType::kNoCell); |
6522 | 6522 |
6523 // Normalize elements to make this operation simple. | 6523 // Normalize elements to make this operation simple. |
6524 bool had_dictionary_elements = object->HasDictionaryElements(); | 6524 bool had_dictionary_elements = object->HasDictionaryElements(); |
6525 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 6525 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
6526 DCHECK(object->HasDictionaryElements() || | 6526 DCHECK(object->HasDictionaryElements() || |
6527 object->HasDictionaryArgumentsElements()); | 6527 object->HasDictionaryArgumentsElements()); |
6528 // Update the dictionary with the new ACCESSOR_CONSTANT property. | 6528 // Update the dictionary with the new ACCESSOR_CONSTANT property. |
6529 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, | 6529 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, |
6530 details); | 6530 details); |
6531 dictionary->set_requires_slow_elements(); | 6531 dictionary->set_requires_slow_elements(); |
(...skipping 6360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12892 // is read-only (a declared const that has not been initialized). | 12892 // is read-only (a declared const that has not been initialized). |
12893 return WriteToReadOnlyProperty( | 12893 return WriteToReadOnlyProperty( |
12894 isolate, object, isolate->factory()->NewNumberFromUint(index), | 12894 isolate, object, isolate->factory()->NewNumberFromUint(index), |
12895 isolate->factory()->undefined_value(), language_mode); | 12895 isolate->factory()->undefined_value(), language_mode); |
12896 } else { | 12896 } else { |
12897 DCHECK(details.IsConfigurable() || !details.IsReadOnly() || | 12897 DCHECK(details.IsConfigurable() || !details.IsReadOnly() || |
12898 element->IsTheHole()); | 12898 element->IsTheHole()); |
12899 dictionary->UpdateMaxNumberKey(index); | 12899 dictionary->UpdateMaxNumberKey(index); |
12900 if (set_mode == DEFINE_PROPERTY) { | 12900 if (set_mode == DEFINE_PROPERTY) { |
12901 details = PropertyDetails(attributes, DATA, details.dictionary_index(), | 12901 details = PropertyDetails(attributes, DATA, details.dictionary_index(), |
12902 PropertyCellType::kInvalid); | 12902 PropertyCellType::kNoCell); |
12903 dictionary->DetailsAtPut(entry, details); | 12903 dictionary->DetailsAtPut(entry, details); |
12904 } | 12904 } |
12905 | 12905 |
12906 // Elements of the arguments object in slow mode might be slow aliases. | 12906 // Elements of the arguments object in slow mode might be slow aliases. |
12907 if (is_arguments && element->IsAliasedArgumentsEntry()) { | 12907 if (is_arguments && element->IsAliasedArgumentsEntry()) { |
12908 Handle<AliasedArgumentsEntry> entry = | 12908 Handle<AliasedArgumentsEntry> entry = |
12909 Handle<AliasedArgumentsEntry>::cast(element); | 12909 Handle<AliasedArgumentsEntry>::cast(element); |
12910 Handle<Context> context(Context::cast(elements->get(0))); | 12910 Handle<Context> context(Context::cast(elements->get(0))); |
12911 int context_index = entry->aliased_context_slot(); | 12911 int context_index = entry->aliased_context_slot(); |
12912 DCHECK(!context->get(context_index)->IsTheHole()); | 12912 DCHECK(!context->get(context_index)->IsTheHole()); |
(...skipping 22 matching lines...) Expand all Loading... |
12935 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12935 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
12936 Handle<String> name = isolate->factory()->NumberToString(number); | 12936 Handle<String> name = isolate->factory()->NumberToString(number); |
12937 Handle<Object> args[] = {name}; | 12937 Handle<Object> args[] = {name}; |
12938 THROW_NEW_ERROR(isolate, | 12938 THROW_NEW_ERROR(isolate, |
12939 NewTypeError("object_not_extensible", | 12939 NewTypeError("object_not_extensible", |
12940 HandleVector(args, arraysize(args))), | 12940 HandleVector(args, arraysize(args))), |
12941 Object); | 12941 Object); |
12942 } | 12942 } |
12943 } | 12943 } |
12944 | 12944 |
12945 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kInvalid); | 12945 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
12946 Handle<SeededNumberDictionary> new_dictionary = | 12946 Handle<SeededNumberDictionary> new_dictionary = |
12947 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, | 12947 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, |
12948 details); | 12948 details); |
12949 if (*dictionary != *new_dictionary) { | 12949 if (*dictionary != *new_dictionary) { |
12950 if (is_arguments) { | 12950 if (is_arguments) { |
12951 elements->set(1, *new_dictionary); | 12951 elements->set(1, *new_dictionary); |
12952 } else { | 12952 } else { |
12953 object->set_elements(*new_dictionary); | 12953 object->set_elements(*new_dictionary); |
12954 } | 12954 } |
12955 dictionary = new_dictionary; | 12955 dictionary = new_dictionary; |
(...skipping 2444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15400 Handle<GlobalObject> global, Handle<Name> name) { | 15400 Handle<GlobalObject> global, Handle<Name> name) { |
15401 DCHECK(!global->HasFastProperties()); | 15401 DCHECK(!global->HasFastProperties()); |
15402 auto dictionary = handle(global->property_dictionary()); | 15402 auto dictionary = handle(global->property_dictionary()); |
15403 int entry = dictionary->FindEntry(name); | 15403 int entry = dictionary->FindEntry(name); |
15404 Handle<PropertyCell> cell; | 15404 Handle<PropertyCell> cell; |
15405 if (entry != NameDictionary::kNotFound) { | 15405 if (entry != NameDictionary::kNotFound) { |
15406 // This call should be idempotent. | 15406 // This call should be idempotent. |
15407 DCHECK(dictionary->DetailsAt(entry).cell_type() == | 15407 DCHECK(dictionary->DetailsAt(entry).cell_type() == |
15408 PropertyCellType::kUninitialized || | 15408 PropertyCellType::kUninitialized || |
15409 dictionary->DetailsAt(entry).cell_type() == | 15409 dictionary->DetailsAt(entry).cell_type() == |
15410 PropertyCellType::kDeleted); | 15410 PropertyCellType::kInvalidated); |
15411 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); | 15411 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); |
15412 cell = handle(PropertyCell::cast(dictionary->ValueAt(entry))); | 15412 cell = handle(PropertyCell::cast(dictionary->ValueAt(entry))); |
15413 DCHECK(cell->value()->IsTheHole()); | 15413 DCHECK(cell->value()->IsTheHole()); |
15414 return cell; | 15414 return cell; |
15415 } | 15415 } |
15416 Isolate* isolate = global->GetIsolate(); | 15416 Isolate* isolate = global->GetIsolate(); |
15417 cell = isolate->factory()->NewPropertyCell(); | 15417 cell = isolate->factory()->NewPropertyCell(); |
15418 PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized); | 15418 PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized); |
15419 dictionary = NameDictionary::Add(dictionary, name, cell, details); | 15419 dictionary = NameDictionary::Add(dictionary, name, cell, details); |
15420 global->set_properties(*dictionary); | 15420 global->set_properties(*dictionary); |
(...skipping 1614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17035 Isolate* isolate = dictionary->GetIsolate(); | 17035 Isolate* isolate = dictionary->GetIsolate(); |
17036 // Swap with a copy. | 17036 // Swap with a copy. |
17037 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); | 17037 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); |
17038 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); | 17038 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
17039 auto new_cell = isolate->factory()->NewPropertyCell(); | 17039 auto new_cell = isolate->factory()->NewPropertyCell(); |
17040 new_cell->set_value(cell->value()); | 17040 new_cell->set_value(cell->value()); |
17041 dictionary->ValueAtPut(entry, *new_cell); | 17041 dictionary->ValueAtPut(entry, *new_cell); |
17042 bool is_the_hole = cell->value()->IsTheHole(); | 17042 bool is_the_hole = cell->value()->IsTheHole(); |
17043 // Cell is officially mutable henceforth. | 17043 // Cell is officially mutable henceforth. |
17044 auto details = dictionary->DetailsAt(entry); | 17044 auto details = dictionary->DetailsAt(entry); |
17045 details = details.set_cell_type(is_the_hole ? PropertyCellType::kDeleted | 17045 details = details.set_cell_type(is_the_hole ? PropertyCellType::kInvalidated |
17046 : PropertyCellType::kMutable); | 17046 : PropertyCellType::kMutable); |
17047 dictionary->DetailsAtPut(entry, details); | 17047 dictionary->DetailsAtPut(entry, details); |
17048 // Old cell is ready for invalidation. | 17048 // Old cell is ready for invalidation. |
17049 if (is_the_hole) { | 17049 if (is_the_hole) { |
17050 cell->set_value(isolate->heap()->undefined_value()); | 17050 cell->set_value(isolate->heap()->undefined_value()); |
17051 } else { | 17051 } else { |
17052 cell->set_value(isolate->heap()->the_hole_value()); | 17052 cell->set_value(isolate->heap()->the_hole_value()); |
17053 } | 17053 } |
17054 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17054 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17055 isolate, DependentCode::kPropertyCellChangedGroup); | 17055 isolate, DependentCode::kPropertyCellChangedGroup); |
17056 return new_cell; | 17056 return new_cell; |
17057 } | 17057 } |
17058 | 17058 |
17059 | 17059 |
| 17060 PropertyCellConstantType PropertyCell::GetConstantType() { |
| 17061 if (value()->IsSmi()) return PropertyCellConstantType::kSmi; |
| 17062 return PropertyCellConstantType::kStableMap; |
| 17063 } |
| 17064 |
| 17065 |
| 17066 static bool RemainsConstantType(Handle<PropertyCell> cell, |
| 17067 Handle<Object> value) { |
| 17068 // TODO(dcarney): double->smi and smi->double transition from kConstant |
| 17069 if (cell->value()->IsSmi() && value->IsSmi()) { |
| 17070 return true; |
| 17071 } else if (cell->value()->IsHeapObject() && value->IsHeapObject()) { |
| 17072 return HeapObject::cast(cell->value())->map() == |
| 17073 HeapObject::cast(*value)->map() && |
| 17074 HeapObject::cast(*value)->map()->is_stable(); |
| 17075 } |
| 17076 return false; |
| 17077 } |
| 17078 |
| 17079 |
17060 PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell, | 17080 PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell, |
17061 Handle<Object> value, | 17081 Handle<Object> value, |
17062 PropertyDetails details) { | 17082 PropertyDetails details) { |
17063 PropertyCellType type = details.cell_type(); | 17083 PropertyCellType type = details.cell_type(); |
17064 DCHECK(!value->IsTheHole()); | 17084 DCHECK(!value->IsTheHole()); |
17065 DCHECK_IMPLIES(cell->value()->IsTheHole(), | 17085 if (cell->value()->IsTheHole()) { |
17066 type == PropertyCellType::kUninitialized || | 17086 switch (type) { |
17067 type == PropertyCellType::kDeleted); | 17087 // Only allow a cell to transition once into constant state. |
| 17088 case PropertyCellType::kUninitialized: |
| 17089 if (value->IsUndefined()) return PropertyCellType::kUndefined; |
| 17090 return PropertyCellType::kConstant; |
| 17091 case PropertyCellType::kInvalidated: |
| 17092 return PropertyCellType::kMutable; |
| 17093 default: |
| 17094 UNREACHABLE(); |
| 17095 return PropertyCellType::kMutable; |
| 17096 } |
| 17097 } |
17068 switch (type) { | 17098 switch (type) { |
17069 // Only allow a cell to transition once into constant state. | |
17070 case PropertyCellType::kUninitialized: | |
17071 if (value->IsUndefined()) return PropertyCellType::kUndefined; | |
17072 return PropertyCellType::kConstant; | |
17073 case PropertyCellType::kUndefined: | 17099 case PropertyCellType::kUndefined: |
17074 return PropertyCellType::kConstant; | 17100 return PropertyCellType::kConstant; |
17075 case PropertyCellType::kConstant: | 17101 case PropertyCellType::kConstant: |
17076 // No transition. | |
17077 if (*value == cell->value()) return PropertyCellType::kConstant; | 17102 if (*value == cell->value()) return PropertyCellType::kConstant; |
17078 // Fall through. | 17103 // Fall through. |
| 17104 case PropertyCellType::kConstantType: |
| 17105 if (RemainsConstantType(cell, value)) { |
| 17106 return PropertyCellType::kConstantType; |
| 17107 } |
| 17108 // Fall through. |
17079 case PropertyCellType::kMutable: | 17109 case PropertyCellType::kMutable: |
17080 return PropertyCellType::kMutable; | 17110 return PropertyCellType::kMutable; |
17081 } | 17111 } |
17082 UNREACHABLE(); | 17112 UNREACHABLE(); |
17083 return PropertyCellType::kMutable; | 17113 return PropertyCellType::kMutable; |
17084 } | 17114 } |
17085 | 17115 |
17086 | 17116 |
17087 Handle<Object> PropertyCell::UpdateCell(Handle<NameDictionary> dictionary, | 17117 Handle<Object> PropertyCell::UpdateCell(Handle<NameDictionary> dictionary, |
17088 int entry, Handle<Object> value, | 17118 int entry, Handle<Object> value, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17121 | 17151 |
17122 auto new_type = UpdatedType(cell, value, original_details); | 17152 auto new_type = UpdatedType(cell, value, original_details); |
17123 if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry); | 17153 if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry); |
17124 | 17154 |
17125 // Install new property details and cell value. | 17155 // Install new property details and cell value. |
17126 details = details.set_cell_type(new_type); | 17156 details = details.set_cell_type(new_type); |
17127 dictionary->DetailsAtPut(entry, details); | 17157 dictionary->DetailsAtPut(entry, details); |
17128 cell->set_value(*value); | 17158 cell->set_value(*value); |
17129 | 17159 |
17130 // Deopt when transitioning from a constant type. | 17160 // Deopt when transitioning from a constant type. |
17131 if (!invalidate && old_type == PropertyCellType::kConstant && | 17161 if (!invalidate && (old_type != new_type)) { |
17132 new_type != PropertyCellType::kConstant) { | |
17133 auto isolate = dictionary->GetIsolate(); | 17162 auto isolate = dictionary->GetIsolate(); |
17134 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17163 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17135 isolate, DependentCode::kPropertyCellChangedGroup); | 17164 isolate, DependentCode::kPropertyCellChangedGroup); |
17136 } | 17165 } |
17137 return value; | 17166 return value; |
17138 } | 17167 } |
17139 | 17168 |
17140 | 17169 |
17141 // static | 17170 // static |
17142 void PropertyCell::AddDependentCompilationInfo(Handle<PropertyCell> cell, | 17171 void PropertyCell::AddDependentCompilationInfo(Handle<PropertyCell> cell, |
17143 CompilationInfo* info) { | 17172 CompilationInfo* info) { |
17144 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( | 17173 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( |
17145 handle(cell->dependent_code(), info->isolate()), | 17174 handle(cell->dependent_code(), info->isolate()), |
17146 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); | 17175 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); |
17147 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 17176 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
17148 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 17177 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
17149 cell, info->zone()); | 17178 cell, info->zone()); |
17150 } | 17179 } |
17151 | 17180 |
17152 } } // namespace v8::internal | 17181 } } // namespace v8::internal |
OLD | NEW |