| 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 <sstream> | 9 #include <sstream> |
| 10 | 10 |
| (...skipping 2661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2672 DCHECK(target_inobject < GetInObjectProperties()); | 2672 DCHECK(target_inobject < GetInObjectProperties()); |
| 2673 if (target_number_of_fields <= target_inobject) { | 2673 if (target_number_of_fields <= target_inobject) { |
| 2674 DCHECK(target_number_of_fields + target_unused == target_inobject); | 2674 DCHECK(target_number_of_fields + target_unused == target_inobject); |
| 2675 return false; | 2675 return false; |
| 2676 } | 2676 } |
| 2677 // Otherwise, properties will need to be moved to the backing store. | 2677 // Otherwise, properties will need to be moved to the backing store. |
| 2678 return true; | 2678 return true; |
| 2679 } | 2679 } |
| 2680 | 2680 |
| 2681 | 2681 |
| 2682 static void UpdatePrototypeUserRegistration(Handle<Map> old_map, | 2682 // static |
| 2683 Handle<Map> new_map, | 2683 void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map, |
| 2684 Isolate* isolate) { | 2684 Handle<Map> new_map, |
| 2685 Isolate* isolate) { |
| 2685 if (!FLAG_track_prototype_users) return; | 2686 if (!FLAG_track_prototype_users) return; |
| 2686 if (!old_map->is_prototype_map()) return; | 2687 if (!old_map->is_prototype_map()) return; |
| 2687 DCHECK(new_map->is_prototype_map()); | 2688 DCHECK(new_map->is_prototype_map()); |
| 2688 bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate); | 2689 bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate); |
| 2689 new_map->set_prototype_info(old_map->prototype_info()); | 2690 new_map->set_prototype_info(old_map->prototype_info()); |
| 2690 old_map->set_prototype_info(Smi::FromInt(0)); | 2691 old_map->set_prototype_info(Smi::FromInt(0)); |
| 2691 if (FLAG_trace_prototype_users) { | 2692 if (FLAG_trace_prototype_users) { |
| 2692 PrintF("Moving prototype_info %p from map %p to map %p.\n", | 2693 PrintF("Moving prototype_info %p from map %p to map %p.\n", |
| 2693 reinterpret_cast<void*>(new_map->prototype_info()), | 2694 reinterpret_cast<void*>(new_map->prototype_info()), |
| 2694 reinterpret_cast<void*>(*old_map), | 2695 reinterpret_cast<void*>(*old_map), |
| (...skipping 9732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12427 } | 12428 } |
| 12428 } | 12429 } |
| 12429 return false; | 12430 return false; |
| 12430 } | 12431 } |
| 12431 | 12432 |
| 12432 | 12433 |
| 12433 // static | 12434 // static |
| 12434 void JSObject::OptimizeAsPrototype(Handle<JSObject> object, | 12435 void JSObject::OptimizeAsPrototype(Handle<JSObject> object, |
| 12435 PrototypeOptimizationMode mode) { | 12436 PrototypeOptimizationMode mode) { |
| 12436 if (object->IsJSGlobalObject()) return; | 12437 if (object->IsJSGlobalObject()) return; |
| 12437 if (object->IsJSGlobalProxy()) return; | |
| 12438 if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) { | 12438 if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) { |
| 12439 // First normalize to ensure all JSFunctions are DATA_CONSTANT. | 12439 // First normalize to ensure all JSFunctions are DATA_CONSTANT. |
| 12440 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0, | 12440 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0, |
| 12441 "NormalizeAsPrototype"); | 12441 "NormalizeAsPrototype"); |
| 12442 } | 12442 } |
| 12443 Handle<Map> previous_map(object->map()); | 12443 Handle<Map> previous_map(object->map()); |
| 12444 if (!object->HasFastProperties()) { | 12444 if (!object->HasFastProperties()) { |
| 12445 JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype"); | 12445 JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype"); |
| 12446 } | 12446 } |
| 12447 if (!object->map()->is_prototype_map()) { | 12447 if (!object->map()->is_prototype_map()) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12485 | 12485 |
| 12486 Handle<Map> current_user = user; | 12486 Handle<Map> current_user = user; |
| 12487 Handle<PrototypeInfo> current_user_info = | 12487 Handle<PrototypeInfo> current_user_info = |
| 12488 Map::GetOrCreatePrototypeInfo(user, isolate); | 12488 Map::GetOrCreatePrototypeInfo(user, isolate); |
| 12489 for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) { | 12489 for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) { |
| 12490 // Walk up the prototype chain as far as links haven't been registered yet. | 12490 // Walk up the prototype chain as far as links haven't been registered yet. |
| 12491 if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) { | 12491 if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) { |
| 12492 break; | 12492 break; |
| 12493 } | 12493 } |
| 12494 Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter); | 12494 Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter); |
| 12495 if (maybe_proto->IsJSGlobalProxy()) continue; | |
| 12496 // Proxies on the prototype chain are not supported. They make it | 12495 // Proxies on the prototype chain are not supported. They make it |
| 12497 // impossible to make any assumptions about the prototype chain anyway. | 12496 // impossible to make any assumptions about the prototype chain anyway. |
| 12498 if (maybe_proto->IsJSProxy()) return; | 12497 if (maybe_proto->IsJSProxy()) return; |
| 12499 Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto); | 12498 Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto); |
| 12500 Handle<PrototypeInfo> proto_info = | 12499 Handle<PrototypeInfo> proto_info = |
| 12501 Map::GetOrCreatePrototypeInfo(proto, isolate); | 12500 Map::GetOrCreatePrototypeInfo(proto, isolate); |
| 12502 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate); | 12501 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate); |
| 12503 int slot = 0; | 12502 int slot = 0; |
| 12504 Handle<WeakFixedArray> new_array = | 12503 Handle<WeakFixedArray> new_array = |
| 12505 WeakFixedArray::Add(maybe_registry, current_user, &slot); | 12504 WeakFixedArray::Add(maybe_registry, current_user, &slot); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 12520 } | 12519 } |
| 12521 | 12520 |
| 12522 | 12521 |
| 12523 // Can be called regardless of whether |user| was actually registered with | 12522 // Can be called regardless of whether |user| was actually registered with |
| 12524 // |prototype|. Returns true when there was a registration. | 12523 // |prototype|. Returns true when there was a registration. |
| 12525 // static | 12524 // static |
| 12526 bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) { | 12525 bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) { |
| 12527 DCHECK(user->is_prototype_map()); | 12526 DCHECK(user->is_prototype_map()); |
| 12528 // If it doesn't have a PrototypeInfo, it was never registered. | 12527 // If it doesn't have a PrototypeInfo, it was never registered. |
| 12529 if (!user->prototype_info()->IsPrototypeInfo()) return false; | 12528 if (!user->prototype_info()->IsPrototypeInfo()) return false; |
| 12530 // If it doesn't have a prototype, it can't be registered. | 12529 // If it had no prototype before, see if it had users that might expect |
| 12531 if (!user->prototype()->IsJSObject()) return false; | 12530 // registration. |
| 12531 if (!user->prototype()->IsJSObject()) { |
| 12532 Object* users = |
| 12533 PrototypeInfo::cast(user->prototype_info())->prototype_users(); |
| 12534 return users->IsWeakFixedArray(); |
| 12535 } |
| 12532 Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate); | 12536 Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate); |
| 12533 Handle<PrototypeInfo> user_info = | 12537 Handle<PrototypeInfo> user_info = |
| 12534 Map::GetOrCreatePrototypeInfo(user, isolate); | 12538 Map::GetOrCreatePrototypeInfo(user, isolate); |
| 12535 int slot = user_info->registry_slot(); | 12539 int slot = user_info->registry_slot(); |
| 12536 if (slot == PrototypeInfo::UNREGISTERED) return false; | 12540 if (slot == PrototypeInfo::UNREGISTERED) return false; |
| 12537 if (prototype->IsJSGlobalProxy()) { | |
| 12538 PrototypeIterator iter(isolate, prototype); | |
| 12539 prototype = PrototypeIterator::GetCurrent<JSObject>(iter); | |
| 12540 } | |
| 12541 DCHECK(prototype->map()->is_prototype_map()); | 12541 DCHECK(prototype->map()->is_prototype_map()); |
| 12542 Object* maybe_proto_info = prototype->map()->prototype_info(); | 12542 Object* maybe_proto_info = prototype->map()->prototype_info(); |
| 12543 // User knows its registry slot, prototype info and user registry must exist. | 12543 // User knows its registry slot, prototype info and user registry must exist. |
| 12544 DCHECK(maybe_proto_info->IsPrototypeInfo()); | 12544 DCHECK(maybe_proto_info->IsPrototypeInfo()); |
| 12545 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info), | 12545 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info), |
| 12546 isolate); | 12546 isolate); |
| 12547 Object* maybe_registry = proto_info->prototype_users(); | 12547 Object* maybe_registry = proto_info->prototype_users(); |
| 12548 DCHECK(maybe_registry->IsWeakFixedArray()); | 12548 DCHECK(maybe_registry->IsWeakFixedArray()); |
| 12549 DCHECK(WeakFixedArray::cast(maybe_registry)->Get(slot) == *user); | 12549 DCHECK(WeakFixedArray::cast(maybe_registry)->Get(slot) == *user); |
| 12550 WeakFixedArray::cast(maybe_registry)->Clear(slot); | 12550 WeakFixedArray::cast(maybe_registry)->Clear(slot); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 12579 // Walk the prototype chain (backwards, towards leaf objects) if necessary. | 12579 // Walk the prototype chain (backwards, towards leaf objects) if necessary. |
| 12580 InvalidatePrototypeChainsInternal(user); | 12580 InvalidatePrototypeChainsInternal(user); |
| 12581 } | 12581 } |
| 12582 } | 12582 } |
| 12583 | 12583 |
| 12584 | 12584 |
| 12585 // static | 12585 // static |
| 12586 void JSObject::InvalidatePrototypeChains(Map* map) { | 12586 void JSObject::InvalidatePrototypeChains(Map* map) { |
| 12587 if (!FLAG_eliminate_prototype_chain_checks) return; | 12587 if (!FLAG_eliminate_prototype_chain_checks) return; |
| 12588 DisallowHeapAllocation no_gc; | 12588 DisallowHeapAllocation no_gc; |
| 12589 if (map->IsJSGlobalProxyMap()) { | |
| 12590 PrototypeIterator iter(map); | |
| 12591 map = iter.GetCurrent<JSObject>()->map(); | |
| 12592 } | |
| 12593 InvalidatePrototypeChainsInternal(map); | 12589 InvalidatePrototypeChainsInternal(map); |
| 12594 } | 12590 } |
| 12595 | 12591 |
| 12596 | 12592 |
| 12597 // static | 12593 // static |
| 12598 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype, | 12594 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype, |
| 12599 Isolate* isolate) { | 12595 Isolate* isolate) { |
| 12600 Object* maybe_proto_info = prototype->map()->prototype_info(); | 12596 Object* maybe_proto_info = prototype->map()->prototype_info(); |
| 12601 if (maybe_proto_info->IsPrototypeInfo()) { | 12597 if (maybe_proto_info->IsPrototypeInfo()) { |
| 12602 return handle(PrototypeInfo::cast(maybe_proto_info), isolate); | 12598 return handle(PrototypeInfo::cast(maybe_proto_info), isolate); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 12619 return proto_info; | 12615 return proto_info; |
| 12620 } | 12616 } |
| 12621 | 12617 |
| 12622 | 12618 |
| 12623 // static | 12619 // static |
| 12624 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, | 12620 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, |
| 12625 Isolate* isolate) { | 12621 Isolate* isolate) { |
| 12626 Handle<Object> maybe_prototype(map->prototype(), isolate); | 12622 Handle<Object> maybe_prototype(map->prototype(), isolate); |
| 12627 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null(); | 12623 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null(); |
| 12628 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype); | 12624 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype); |
| 12629 if (prototype->IsJSGlobalProxy()) { | |
| 12630 PrototypeIterator iter(isolate, prototype); | |
| 12631 prototype = PrototypeIterator::GetCurrent<JSObject>(iter); | |
| 12632 } | |
| 12633 // Ensure the prototype is registered with its own prototypes so its cell | 12625 // Ensure the prototype is registered with its own prototypes so its cell |
| 12634 // will be invalidated when necessary. | 12626 // will be invalidated when necessary. |
| 12635 JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate), | 12627 JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate), |
| 12636 isolate); | 12628 isolate); |
| 12637 Handle<PrototypeInfo> proto_info = | 12629 Handle<PrototypeInfo> proto_info = |
| 12638 GetOrCreatePrototypeInfo(prototype, isolate); | 12630 GetOrCreatePrototypeInfo(prototype, isolate); |
| 12639 Object* maybe_cell = proto_info->validity_cell(); | 12631 Object* maybe_cell = proto_info->validity_cell(); |
| 12640 // Return existing cell if it's still valid. | 12632 // Return existing cell if it's still valid. |
| 12641 if (maybe_cell->IsCell()) { | 12633 if (maybe_cell->IsCell()) { |
| 12642 Handle<Cell> cell(Cell::cast(maybe_cell), isolate); | 12634 Handle<Cell> cell(Cell::cast(maybe_cell), isolate); |
| (...skipping 6850 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 19493 if (cell->value() != *new_value) { | 19485 if (cell->value() != *new_value) { |
| 19494 cell->set_value(*new_value); | 19486 cell->set_value(*new_value); |
| 19495 Isolate* isolate = cell->GetIsolate(); | 19487 Isolate* isolate = cell->GetIsolate(); |
| 19496 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19488 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 19497 isolate, DependentCode::kPropertyCellChangedGroup); | 19489 isolate, DependentCode::kPropertyCellChangedGroup); |
| 19498 } | 19490 } |
| 19499 } | 19491 } |
| 19500 | 19492 |
| 19501 } // namespace internal | 19493 } // namespace internal |
| 19502 } // namespace v8 | 19494 } // namespace v8 |
| OLD | NEW |