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 |