| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 "src/objects.h" | 5 #include "src/objects.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 #include <iomanip> | 8 #include <iomanip> |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <sstream> | 10 #include <sstream> |
| (...skipping 3189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3200 } | 3200 } |
| 3201 // Otherwise, properties will need to be moved to the backing store. | 3201 // Otherwise, properties will need to be moved to the backing store. |
| 3202 return true; | 3202 return true; |
| 3203 } | 3203 } |
| 3204 | 3204 |
| 3205 | 3205 |
| 3206 // static | 3206 // static |
| 3207 void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map, | 3207 void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map, |
| 3208 Handle<Map> new_map, | 3208 Handle<Map> new_map, |
| 3209 Isolate* isolate) { | 3209 Isolate* isolate) { |
| 3210 if (!old_map->is_prototype_map()) return; | 3210 DCHECK(old_map->is_prototype_map()); |
| 3211 DCHECK(new_map->is_prototype_map()); | 3211 DCHECK(new_map->is_prototype_map()); |
| 3212 bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate); | 3212 bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate); |
| 3213 new_map->set_prototype_info(old_map->prototype_info()); | 3213 new_map->set_prototype_info(old_map->prototype_info()); |
| 3214 old_map->set_prototype_info(Smi::kZero); | 3214 old_map->set_prototype_info(Smi::kZero); |
| 3215 if (FLAG_trace_prototype_users) { | 3215 if (FLAG_trace_prototype_users) { |
| 3216 PrintF("Moving prototype_info %p from map %p to map %p.\n", | 3216 PrintF("Moving prototype_info %p from map %p to map %p.\n", |
| 3217 reinterpret_cast<void*>(new_map->prototype_info()), | 3217 reinterpret_cast<void*>(new_map->prototype_info()), |
| 3218 reinterpret_cast<void*>(*old_map), | 3218 reinterpret_cast<void*>(*old_map), |
| 3219 reinterpret_cast<void*>(*new_map)); | 3219 reinterpret_cast<void*>(*new_map)); |
| 3220 } | 3220 } |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3567 if (FLAG_trace_normalization) { | 3567 if (FLAG_trace_normalization) { |
| 3568 OFStream os(stdout); | 3568 OFStream os(stdout); |
| 3569 os << "Object properties have been normalized:\n"; | 3569 os << "Object properties have been normalized:\n"; |
| 3570 object->Print(os); | 3570 object->Print(os); |
| 3571 } | 3571 } |
| 3572 #endif | 3572 #endif |
| 3573 } | 3573 } |
| 3574 | 3574 |
| 3575 } // namespace | 3575 } // namespace |
| 3576 | 3576 |
| 3577 // static |
| 3578 void JSObject::NotifyMapChange(Handle<Map> old_map, Handle<Map> new_map, |
| 3579 Isolate* isolate) { |
| 3580 if (!old_map->is_prototype_map()) return; |
| 3581 |
| 3582 InvalidatePrototypeChains(*old_map); |
| 3583 |
| 3584 // If the map was registered with its prototype before, ensure that it |
| 3585 // registers with its new prototype now. This preserves the invariant that |
| 3586 // when a map on a prototype chain is registered with its prototype, then |
| 3587 // all prototypes further up the chain are also registered with their |
| 3588 // respective prototypes. |
| 3589 UpdatePrototypeUserRegistration(old_map, new_map, isolate); |
| 3590 } |
| 3591 |
| 3577 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, | 3592 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, |
| 3578 int expected_additional_properties) { | 3593 int expected_additional_properties) { |
| 3579 if (object->map() == *new_map) return; | 3594 if (object->map() == *new_map) return; |
| 3580 Handle<Map> old_map(object->map()); | 3595 Handle<Map> old_map(object->map()); |
| 3581 if (old_map->is_prototype_map()) { | 3596 NotifyMapChange(old_map, new_map, new_map->GetIsolate()); |
| 3582 // If this object is a prototype (the callee will check), invalidate any | |
| 3583 // prototype chains involving it. | |
| 3584 InvalidatePrototypeChains(object->map()); | |
| 3585 | |
| 3586 // If the map was registered with its prototype before, ensure that it | |
| 3587 // registers with its new prototype now. This preserves the invariant that | |
| 3588 // when a map on a prototype chain is registered with its prototype, then | |
| 3589 // all prototypes further up the chain are also registered with their | |
| 3590 // respective prototypes. | |
| 3591 UpdatePrototypeUserRegistration(old_map, new_map, new_map->GetIsolate()); | |
| 3592 } | |
| 3593 | 3597 |
| 3594 if (old_map->is_dictionary_map()) { | 3598 if (old_map->is_dictionary_map()) { |
| 3595 // For slow-to-fast migrations JSObject::MigrateSlowToFast() | 3599 // For slow-to-fast migrations JSObject::MigrateSlowToFast() |
| 3596 // must be used instead. | 3600 // must be used instead. |
| 3597 CHECK(new_map->is_dictionary_map()); | 3601 CHECK(new_map->is_dictionary_map()); |
| 3598 | 3602 |
| 3599 // Slow-to-slow migration is trivial. | 3603 // Slow-to-slow migration is trivial. |
| 3600 object->set_map(*new_map); | 3604 object->set_map(*new_map); |
| 3601 } else if (!new_map->is_dictionary_map()) { | 3605 } else if (!new_map->is_dictionary_map()) { |
| 3602 MigrateFastToFast(object, new_map); | 3606 MigrateFastToFast(object, new_map); |
| (...skipping 2409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6012 } | 6016 } |
| 6013 | 6017 |
| 6014 Handle<Map> old_map(object->map(), isolate); | 6018 Handle<Map> old_map(object->map(), isolate); |
| 6015 | 6019 |
| 6016 int inobject_props = old_map->GetInObjectProperties(); | 6020 int inobject_props = old_map->GetInObjectProperties(); |
| 6017 | 6021 |
| 6018 // Allocate new map. | 6022 // Allocate new map. |
| 6019 Handle<Map> new_map = Map::CopyDropDescriptors(old_map); | 6023 Handle<Map> new_map = Map::CopyDropDescriptors(old_map); |
| 6020 new_map->set_dictionary_map(false); | 6024 new_map->set_dictionary_map(false); |
| 6021 | 6025 |
| 6022 UpdatePrototypeUserRegistration(old_map, new_map, isolate); | 6026 NotifyMapChange(old_map, new_map, isolate); |
| 6023 | 6027 |
| 6024 #if TRACE_MAPS | 6028 #if TRACE_MAPS |
| 6025 if (FLAG_trace_maps) { | 6029 if (FLAG_trace_maps) { |
| 6026 PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n", | 6030 PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n", |
| 6027 reinterpret_cast<void*>(*old_map), reinterpret_cast<void*>(*new_map), | 6031 reinterpret_cast<void*>(*old_map), reinterpret_cast<void*>(*new_map), |
| 6028 reason); | 6032 reason); |
| 6029 } | 6033 } |
| 6030 #endif | 6034 #endif |
| 6031 | 6035 |
| 6032 if (instance_descriptor_length == 0) { | 6036 if (instance_descriptor_length == 0) { |
| (...skipping 6671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12704 WeakFixedArray::cast(maybe_registry)->Clear(slot); | 12708 WeakFixedArray::cast(maybe_registry)->Clear(slot); |
| 12705 if (FLAG_trace_prototype_users) { | 12709 if (FLAG_trace_prototype_users) { |
| 12706 PrintF("Unregistering %p as a user of prototype %p.\n", | 12710 PrintF("Unregistering %p as a user of prototype %p.\n", |
| 12707 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype)); | 12711 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype)); |
| 12708 } | 12712 } |
| 12709 return true; | 12713 return true; |
| 12710 } | 12714 } |
| 12711 | 12715 |
| 12712 | 12716 |
| 12713 static void InvalidatePrototypeChainsInternal(Map* map) { | 12717 static void InvalidatePrototypeChainsInternal(Map* map) { |
| 12714 if (!map->is_prototype_map()) return; | 12718 DCHECK(map->is_prototype_map()); |
| 12715 if (FLAG_trace_prototype_users) { | 12719 if (FLAG_trace_prototype_users) { |
| 12716 PrintF("Invalidating prototype map %p 's cell\n", | 12720 PrintF("Invalidating prototype map %p 's cell\n", |
| 12717 reinterpret_cast<void*>(map)); | 12721 reinterpret_cast<void*>(map)); |
| 12718 } | 12722 } |
| 12719 Object* maybe_proto_info = map->prototype_info(); | 12723 Object* maybe_proto_info = map->prototype_info(); |
| 12720 if (!maybe_proto_info->IsPrototypeInfo()) return; | 12724 if (!maybe_proto_info->IsPrototypeInfo()) return; |
| 12721 PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info); | 12725 PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info); |
| 12722 Object* maybe_cell = proto_info->validity_cell(); | 12726 Object* maybe_cell = proto_info->validity_cell(); |
| 12723 if (maybe_cell->IsCell()) { | 12727 if (maybe_cell->IsCell()) { |
| 12724 // Just set the value; the cell will be replaced lazily. | 12728 // Just set the value; the cell will be replaced lazily. |
| (...skipping 7696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20421 // depend on this. | 20425 // depend on this. |
| 20422 return DICTIONARY_ELEMENTS; | 20426 return DICTIONARY_ELEMENTS; |
| 20423 } | 20427 } |
| 20424 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 20428 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
| 20425 return kind; | 20429 return kind; |
| 20426 } | 20430 } |
| 20427 } | 20431 } |
| 20428 | 20432 |
| 20429 } // namespace internal | 20433 } // namespace internal |
| 20430 } // namespace v8 | 20434 } // namespace v8 |
| OLD | NEW |