| 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 1742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1753 DCHECK(target_inobject < inobject_properties()); | 1753 DCHECK(target_inobject < inobject_properties()); |
| 1754 if (target_number_of_fields <= target_inobject) { | 1754 if (target_number_of_fields <= target_inobject) { |
| 1755 DCHECK(target_number_of_fields + target_unused == target_inobject); | 1755 DCHECK(target_number_of_fields + target_unused == target_inobject); |
| 1756 return false; | 1756 return false; |
| 1757 } | 1757 } |
| 1758 // Otherwise, properties will need to be moved to the backing store. | 1758 // Otherwise, properties will need to be moved to the backing store. |
| 1759 return true; | 1759 return true; |
| 1760 } | 1760 } |
| 1761 | 1761 |
| 1762 | 1762 |
| 1763 static void UpdatePrototypeUserRegistration(Handle<Map> old_map, |
| 1764 Handle<Map> new_map, |
| 1765 Isolate* isolate) { |
| 1766 if (!FLAG_track_prototype_users) return; |
| 1767 if (!old_map->is_prototype_map()) return; |
| 1768 DCHECK(new_map->is_prototype_map()); |
| 1769 bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate); |
| 1770 new_map->set_prototype_info(old_map->prototype_info()); |
| 1771 old_map->set_prototype_info(Smi::FromInt(0)); |
| 1772 if (FLAG_trace_prototype_users) { |
| 1773 PrintF("Moving prototype_info %p from map %p to map %p.\n", |
| 1774 reinterpret_cast<void*>(new_map->prototype_info()), |
| 1775 reinterpret_cast<void*>(*old_map), |
| 1776 reinterpret_cast<void*>(*new_map)); |
| 1777 } |
| 1778 if (was_registered) { |
| 1779 if (new_map->prototype_info()->IsPrototypeInfo()) { |
| 1780 // The new map isn't registered with its prototype yet; reflect this fact |
| 1781 // in the PrototypeInfo it just inherited from the old map. |
| 1782 PrototypeInfo::cast(new_map->prototype_info()) |
| 1783 ->set_registry_slot(PrototypeInfo::UNREGISTERED); |
| 1784 } |
| 1785 JSObject::LazyRegisterPrototypeUser(new_map, isolate); |
| 1786 } |
| 1787 } |
| 1788 |
| 1789 |
| 1763 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, | 1790 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, |
| 1764 int expected_additional_properties) { | 1791 int expected_additional_properties) { |
| 1765 if (object->map() == *new_map) return; | 1792 if (object->map() == *new_map) return; |
| 1766 // If this object is a prototype (the callee will check), invalidate any | 1793 // If this object is a prototype (the callee will check), invalidate any |
| 1767 // prototype chains involving it. | 1794 // prototype chains involving it. |
| 1768 InvalidatePrototypeChains(object->map()); | 1795 InvalidatePrototypeChains(object->map()); |
| 1769 Handle<Map> old_map(object->map()); | 1796 Handle<Map> old_map(object->map()); |
| 1770 | 1797 |
| 1771 // If the map was registered with its prototype before, ensure that it | 1798 // If the map was registered with its prototype before, ensure that it |
| 1772 // registers with its new prototype now. This preserves the invariant that | 1799 // registers with its new prototype now. This preserves the invariant that |
| 1773 // when a map on a prototype chain is registered with its prototype, then | 1800 // when a map on a prototype chain is registered with its prototype, then |
| 1774 // all prototypes further up the chain are also registered with their | 1801 // all prototypes further up the chain are also registered with their |
| 1775 // respective prototypes. | 1802 // respective prototypes. |
| 1776 Object* maybe_old_prototype = old_map->prototype(); | 1803 UpdatePrototypeUserRegistration(old_map, new_map, new_map->GetIsolate()); |
| 1777 if (FLAG_track_prototype_users && old_map->is_prototype_map() && | |
| 1778 maybe_old_prototype->IsJSObject()) { | |
| 1779 Handle<JSObject> old_prototype(JSObject::cast(maybe_old_prototype)); | |
| 1780 bool was_registered = | |
| 1781 JSObject::UnregisterPrototypeUser(old_prototype, old_map); | |
| 1782 if (was_registered) { | |
| 1783 JSObject::LazyRegisterPrototypeUser(new_map, new_map->GetIsolate()); | |
| 1784 } | |
| 1785 } | |
| 1786 | 1804 |
| 1787 if (object->HasFastProperties()) { | 1805 if (object->HasFastProperties()) { |
| 1788 if (!new_map->is_dictionary_map()) { | 1806 if (!new_map->is_dictionary_map()) { |
| 1789 MigrateFastToFast(object, new_map); | 1807 MigrateFastToFast(object, new_map); |
| 1790 if (old_map->is_prototype_map()) { | 1808 if (old_map->is_prototype_map()) { |
| 1791 // Clear out the old descriptor array to avoid problems to sharing | 1809 // Clear out the old descriptor array to avoid problems to sharing |
| 1792 // the descriptor array without using an explicit. | 1810 // the descriptor array without using an explicit. |
| 1793 old_map->InitializeDescriptors( | 1811 old_map->InitializeDescriptors( |
| 1794 old_map->GetHeap()->empty_descriptor_array(), | 1812 old_map->GetHeap()->empty_descriptor_array(), |
| 1795 LayoutDescriptor::FastPointerLayout()); | 1813 LayoutDescriptor::FastPointerLayout()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1808 | 1826 |
| 1809 // Slow-to-slow migration is trivial. | 1827 // Slow-to-slow migration is trivial. |
| 1810 object->set_map(*new_map); | 1828 object->set_map(*new_map); |
| 1811 } | 1829 } |
| 1812 | 1830 |
| 1813 // Careful: Don't allocate here! | 1831 // Careful: Don't allocate here! |
| 1814 // For some callers of this method, |object| might be in an inconsistent | 1832 // For some callers of this method, |object| might be in an inconsistent |
| 1815 // state now: the new map might have a new elements_kind, but the object's | 1833 // state now: the new map might have a new elements_kind, but the object's |
| 1816 // elements pointer hasn't been updated yet. Callers will fix this, but in | 1834 // elements pointer hasn't been updated yet. Callers will fix this, but in |
| 1817 // the meantime, (indirectly) calling JSObjectVerify() must be avoided. | 1835 // the meantime, (indirectly) calling JSObjectVerify() must be avoided. |
| 1818 DisallowHeapAllocation no_object_verification; | 1836 // When adding code here, add a DisallowHeapAllocation too. |
| 1819 | |
| 1820 if (old_map->is_prototype_map() && FLAG_track_prototype_users) { | |
| 1821 DCHECK(new_map->is_prototype_map()); | |
| 1822 DCHECK(object->map() == *new_map); | |
| 1823 new_map->set_prototype_info(old_map->prototype_info()); | |
| 1824 old_map->set_prototype_info(Smi::FromInt(0)); | |
| 1825 if (FLAG_trace_prototype_users) { | |
| 1826 PrintF("Moving prototype_info %p from map %p to map %p.\n", | |
| 1827 reinterpret_cast<void*>(new_map->prototype_info()), | |
| 1828 reinterpret_cast<void*>(*old_map), | |
| 1829 reinterpret_cast<void*>(*new_map)); | |
| 1830 } | |
| 1831 } | |
| 1832 } | 1837 } |
| 1833 | 1838 |
| 1834 | 1839 |
| 1835 // To migrate a fast instance to a fast map: | 1840 // To migrate a fast instance to a fast map: |
| 1836 // - First check whether the instance needs to be rewritten. If not, simply | 1841 // - First check whether the instance needs to be rewritten. If not, simply |
| 1837 // change the map. | 1842 // change the map. |
| 1838 // - Otherwise, allocate a fixed array large enough to hold all fields, in | 1843 // - Otherwise, allocate a fixed array large enough to hold all fields, in |
| 1839 // addition to unused space. | 1844 // addition to unused space. |
| 1840 // - Copy all existing properties in, in the following order: backing store | 1845 // - Copy all existing properties in, in the following order: backing store |
| 1841 // properties, unused fields, inobject properties. | 1846 // properties, unused fields, inobject properties. |
| (...skipping 2805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4647 } | 4652 } |
| 4648 | 4653 |
| 4649 Handle<Map> old_map(object->map(), isolate); | 4654 Handle<Map> old_map(object->map(), isolate); |
| 4650 | 4655 |
| 4651 int inobject_props = old_map->inobject_properties(); | 4656 int inobject_props = old_map->inobject_properties(); |
| 4652 | 4657 |
| 4653 // Allocate new map. | 4658 // Allocate new map. |
| 4654 Handle<Map> new_map = Map::CopyDropDescriptors(old_map); | 4659 Handle<Map> new_map = Map::CopyDropDescriptors(old_map); |
| 4655 new_map->set_dictionary_map(false); | 4660 new_map->set_dictionary_map(false); |
| 4656 | 4661 |
| 4657 if (old_map->is_prototype_map() && FLAG_track_prototype_users) { | 4662 UpdatePrototypeUserRegistration(old_map, new_map, isolate); |
| 4658 DCHECK(new_map->is_prototype_map()); | |
| 4659 | |
| 4660 Object* maybe_old_prototype = old_map->prototype(); | |
| 4661 if (maybe_old_prototype->IsJSObject()) { | |
| 4662 Handle<JSObject> old_prototype(JSObject::cast(maybe_old_prototype)); | |
| 4663 bool was_registered = | |
| 4664 JSObject::UnregisterPrototypeUser(old_prototype, old_map); | |
| 4665 if (was_registered) { | |
| 4666 JSObject::LazyRegisterPrototypeUser(new_map, isolate); | |
| 4667 } | |
| 4668 } | |
| 4669 new_map->set_prototype_info(old_map->prototype_info()); | |
| 4670 old_map->set_prototype_info(Smi::FromInt(0)); | |
| 4671 if (FLAG_trace_prototype_users) { | |
| 4672 PrintF("Moving prototype_info %p from map %p to map %p.\n", | |
| 4673 reinterpret_cast<void*>(new_map->prototype_info()), | |
| 4674 reinterpret_cast<void*>(*old_map), | |
| 4675 reinterpret_cast<void*>(*new_map)); | |
| 4676 } | |
| 4677 } | |
| 4678 | 4663 |
| 4679 #if TRACE_MAPS | 4664 #if TRACE_MAPS |
| 4680 if (FLAG_trace_maps) { | 4665 if (FLAG_trace_maps) { |
| 4681 PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n", | 4666 PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n", |
| 4682 reinterpret_cast<void*>(*old_map), reinterpret_cast<void*>(*new_map), | 4667 reinterpret_cast<void*>(*old_map), reinterpret_cast<void*>(*new_map), |
| 4683 reason); | 4668 reason); |
| 4684 } | 4669 } |
| 4685 #endif | 4670 #endif |
| 4686 | 4671 |
| 4687 if (instance_descriptor_length == 0) { | 4672 if (instance_descriptor_length == 0) { |
| (...skipping 3373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8061 : array->GetIsolate()->factory()->NewWeakCell(value); | 8046 : array->GetIsolate()->factory()->NewWeakCell(value); |
| 8062 Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell); | 8047 Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell); |
| 8063 if (FLAG_trace_weak_arrays) { | 8048 if (FLAG_trace_weak_arrays) { |
| 8064 PrintF("[WeakFixedArray: storing at index %d ]\n", index); | 8049 PrintF("[WeakFixedArray: storing at index %d ]\n", index); |
| 8065 } | 8050 } |
| 8066 array->set_last_used_index(index); | 8051 array->set_last_used_index(index); |
| 8067 } | 8052 } |
| 8068 | 8053 |
| 8069 | 8054 |
| 8070 // static | 8055 // static |
| 8071 Handle<WeakFixedArray> WeakFixedArray::Add( | 8056 Handle<WeakFixedArray> WeakFixedArray::Add(Handle<Object> maybe_array, |
| 8072 Handle<Object> maybe_array, Handle<HeapObject> value, | 8057 Handle<HeapObject> value, |
| 8073 SearchForDuplicates search_for_duplicates, bool* was_present) { | 8058 int* assigned_index) { |
| 8074 Handle<WeakFixedArray> array = | 8059 Handle<WeakFixedArray> array = |
| 8075 (maybe_array.is_null() || !maybe_array->IsWeakFixedArray()) | 8060 (maybe_array.is_null() || !maybe_array->IsWeakFixedArray()) |
| 8076 ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null()) | 8061 ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null()) |
| 8077 : Handle<WeakFixedArray>::cast(maybe_array); | 8062 : Handle<WeakFixedArray>::cast(maybe_array); |
| 8078 if (was_present != NULL) *was_present = false; | |
| 8079 if (search_for_duplicates == kAddIfNotFound) { | |
| 8080 for (int i = 0; i < array->Length(); ++i) { | |
| 8081 if (array->Get(i) == *value) { | |
| 8082 if (was_present != NULL) *was_present = true; | |
| 8083 return array; | |
| 8084 } | |
| 8085 } | |
| 8086 #if 0 // Enable this if you want to check your search_for_duplicates flags. | |
| 8087 } else { | |
| 8088 for (int i = 0; i < array->Length(); ++i) { | |
| 8089 DCHECK_NE(*value, array->Get(i)); | |
| 8090 } | |
| 8091 #endif | |
| 8092 } | |
| 8093 | |
| 8094 // Try to store the new entry if there's room. Optimize for consecutive | 8063 // Try to store the new entry if there's room. Optimize for consecutive |
| 8095 // accesses. | 8064 // accesses. |
| 8096 int first_index = array->last_used_index(); | 8065 int first_index = array->last_used_index(); |
| 8097 if (array->Length() > 0) { | 8066 int length = array->Length(); |
| 8067 if (length > 0) { |
| 8098 for (int i = first_index;;) { | 8068 for (int i = first_index;;) { |
| 8099 if (array->IsEmptySlot((i))) { | 8069 if (array->IsEmptySlot((i))) { |
| 8100 WeakFixedArray::Set(array, i, value); | 8070 WeakFixedArray::Set(array, i, value); |
| 8071 if (assigned_index != NULL) *assigned_index = i; |
| 8101 return array; | 8072 return array; |
| 8102 } | 8073 } |
| 8103 if (FLAG_trace_weak_arrays) { | 8074 if (FLAG_trace_weak_arrays) { |
| 8104 PrintF("[WeakFixedArray: searching for free slot]\n"); | 8075 PrintF("[WeakFixedArray: searching for free slot]\n"); |
| 8105 } | 8076 } |
| 8106 i = (i + 1) % array->Length(); | 8077 i = (i + 1) % length; |
| 8107 if (i == first_index) break; | 8078 if (i == first_index) break; |
| 8108 } | 8079 } |
| 8109 } | 8080 } |
| 8110 | 8081 |
| 8111 // No usable slot found, grow the array. | 8082 // No usable slot found, grow the array. |
| 8112 int new_length = | 8083 int new_length = length == 0 ? 1 : length + (length >> 1) + 4; |
| 8113 array->Length() == 0 ? 1 : array->Length() + (array->Length() >> 1) + 4; | |
| 8114 Handle<WeakFixedArray> new_array = | 8084 Handle<WeakFixedArray> new_array = |
| 8115 Allocate(array->GetIsolate(), new_length, array); | 8085 Allocate(array->GetIsolate(), new_length, array); |
| 8116 if (FLAG_trace_weak_arrays) { | 8086 if (FLAG_trace_weak_arrays) { |
| 8117 PrintF("[WeakFixedArray: growing to size %d ]\n", new_length); | 8087 PrintF("[WeakFixedArray: growing to size %d ]\n", new_length); |
| 8118 } | 8088 } |
| 8119 WeakFixedArray::Set(new_array, array->Length(), value); | 8089 WeakFixedArray::Set(new_array, length, value); |
| 8090 if (assigned_index != NULL) *assigned_index = length; |
| 8120 return new_array; | 8091 return new_array; |
| 8121 } | 8092 } |
| 8122 | 8093 |
| 8123 | 8094 |
| 8095 template <class CompactionCallback> |
| 8124 void WeakFixedArray::Compact() { | 8096 void WeakFixedArray::Compact() { |
| 8125 FixedArray* array = FixedArray::cast(this); | 8097 FixedArray* array = FixedArray::cast(this); |
| 8126 int new_length = kFirstIndex; | 8098 int new_length = kFirstIndex; |
| 8127 for (int i = kFirstIndex; i < array->length(); i++) { | 8099 for (int i = kFirstIndex; i < array->length(); i++) { |
| 8128 Object* element = array->get(i); | 8100 Object* element = array->get(i); |
| 8129 if (element->IsSmi()) continue; | 8101 if (element->IsSmi()) continue; |
| 8130 if (WeakCell::cast(element)->cleared()) continue; | 8102 if (WeakCell::cast(element)->cleared()) continue; |
| 8103 Object* value = WeakCell::cast(element)->value(); |
| 8104 CompactionCallback::Callback(value, i - kFirstIndex, |
| 8105 new_length - kFirstIndex); |
| 8131 array->set(new_length++, element); | 8106 array->set(new_length++, element); |
| 8132 } | 8107 } |
| 8133 array->Shrink(new_length); | 8108 array->Shrink(new_length); |
| 8134 set_last_used_index(0); | 8109 set_last_used_index(0); |
| 8135 } | 8110 } |
| 8136 | 8111 |
| 8137 | 8112 |
| 8113 void JSObject::PrototypeRegistryCompactionCallback::Callback(Object* value, |
| 8114 int old_index, |
| 8115 int new_index) { |
| 8116 DCHECK(value->IsMap() && Map::cast(value)->is_prototype_map()); |
| 8117 Map* map = Map::cast(value); |
| 8118 DCHECK(map->prototype_info()->IsPrototypeInfo()); |
| 8119 PrototypeInfo* proto_info = PrototypeInfo::cast(map->prototype_info()); |
| 8120 DCHECK_EQ(old_index, proto_info->registry_slot()); |
| 8121 proto_info->set_registry_slot(new_index); |
| 8122 } |
| 8123 |
| 8124 |
| 8125 template void WeakFixedArray::Compact<WeakFixedArray::NullCallback>(); |
| 8126 template void |
| 8127 WeakFixedArray::Compact<JSObject::PrototypeRegistryCompactionCallback>(); |
| 8128 |
| 8129 |
| 8138 bool WeakFixedArray::Remove(Handle<HeapObject> value) { | 8130 bool WeakFixedArray::Remove(Handle<HeapObject> value) { |
| 8139 if (Length() == 0) return false; | 8131 if (Length() == 0) return false; |
| 8140 // Optimize for the most recently added element to be removed again. | 8132 // Optimize for the most recently added element to be removed again. |
| 8141 int first_index = last_used_index(); | 8133 int first_index = last_used_index(); |
| 8142 for (int i = first_index;;) { | 8134 for (int i = first_index;;) { |
| 8143 if (Get(i) == *value) { | 8135 if (Get(i) == *value) { |
| 8144 Clear(i); | 8136 Clear(i); |
| 8145 // Users of WeakFixedArray should make sure that there are no duplicates, | 8137 // Users of WeakFixedArray should make sure that there are no duplicates. |
| 8146 // they can use Add(..., kAddIfNotFound) if necessary. | |
| 8147 return true; | 8138 return true; |
| 8148 } | 8139 } |
| 8149 i = (i + 1) % Length(); | 8140 i = (i + 1) % Length(); |
| 8150 if (i == first_index) return false; | 8141 if (i == first_index) return false; |
| 8151 } | 8142 } |
| 8152 UNREACHABLE(); | 8143 UNREACHABLE(); |
| 8153 } | 8144 } |
| 8154 | 8145 |
| 8155 | 8146 |
| 8156 // static | 8147 // static |
| (...skipping 1697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9854 | 9845 |
| 9855 | 9846 |
| 9856 // static | 9847 // static |
| 9857 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) { | 9848 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) { |
| 9858 DCHECK(FLAG_track_prototype_users); | 9849 DCHECK(FLAG_track_prototype_users); |
| 9859 // Contract: In line with InvalidatePrototypeChains()'s requirements, | 9850 // Contract: In line with InvalidatePrototypeChains()'s requirements, |
| 9860 // leaf maps don't need to register as users, only prototypes do. | 9851 // leaf maps don't need to register as users, only prototypes do. |
| 9861 DCHECK(user->is_prototype_map()); | 9852 DCHECK(user->is_prototype_map()); |
| 9862 | 9853 |
| 9863 Handle<Map> current_user = user; | 9854 Handle<Map> current_user = user; |
| 9855 Handle<PrototypeInfo> current_user_info = |
| 9856 Map::GetOrCreatePrototypeInfo(user, isolate); |
| 9864 for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) { | 9857 for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) { |
| 9858 // Walk up the prototype chain as far as links haven't been registered yet. |
| 9859 if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) { |
| 9860 break; |
| 9861 } |
| 9865 Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter); | 9862 Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter); |
| 9866 if (maybe_proto->IsJSGlobalProxy()) continue; | 9863 if (maybe_proto->IsJSGlobalProxy()) continue; |
| 9867 // Proxies on the prototype chain are not supported. | 9864 // Proxies on the prototype chain are not supported. |
| 9868 if (maybe_proto->IsJSProxy()) return; | 9865 if (maybe_proto->IsJSProxy()) return; |
| 9869 Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto); | 9866 Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto); |
| 9870 bool just_registered = | 9867 Handle<PrototypeInfo> proto_info = |
| 9871 RegisterPrototypeUserIfNotRegistered(proto, current_user, isolate); | 9868 Map::GetOrCreatePrototypeInfo(proto, isolate); |
| 9872 // Walk up the prototype chain as far as links haven't been registered yet. | 9869 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate); |
| 9873 if (!just_registered) break; | 9870 int slot = 0; |
| 9871 Handle<WeakFixedArray> new_array = |
| 9872 WeakFixedArray::Add(maybe_registry, current_user, &slot); |
| 9873 current_user_info->set_registry_slot(slot); |
| 9874 if (!maybe_registry.is_identical_to(new_array)) { |
| 9875 proto_info->set_prototype_users(*new_array); |
| 9876 } |
| 9877 if (FLAG_trace_prototype_users) { |
| 9878 PrintF("Registering %p as a user of prototype %p (map=%p).\n", |
| 9879 reinterpret_cast<void*>(*current_user), |
| 9880 reinterpret_cast<void*>(*proto), |
| 9881 reinterpret_cast<void*>(proto->map())); |
| 9882 } |
| 9883 |
| 9874 current_user = handle(proto->map(), isolate); | 9884 current_user = handle(proto->map(), isolate); |
| 9885 current_user_info = proto_info; |
| 9875 } | 9886 } |
| 9876 } | 9887 } |
| 9877 | 9888 |
| 9878 | 9889 |
| 9879 // Returns true if the user was not yet registered. | |
| 9880 // static | |
| 9881 bool JSObject::RegisterPrototypeUserIfNotRegistered(Handle<JSObject> prototype, | |
| 9882 Handle<HeapObject> user, | |
| 9883 Isolate* isolate) { | |
| 9884 Handle<PrototypeInfo> proto_info = | |
| 9885 Map::GetOrCreatePrototypeInfo(prototype, isolate); | |
| 9886 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate); | |
| 9887 bool was_present = false; | |
| 9888 Handle<WeakFixedArray> new_array = WeakFixedArray::Add( | |
| 9889 maybe_registry, user, WeakFixedArray::kAddIfNotFound, &was_present); | |
| 9890 if (!maybe_registry.is_identical_to(new_array)) { | |
| 9891 proto_info->set_prototype_users(*new_array); | |
| 9892 } | |
| 9893 if (FLAG_trace_prototype_users && !was_present) { | |
| 9894 PrintF("Registering %p as a user of prototype %p (map=%p).\n", | |
| 9895 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype), | |
| 9896 reinterpret_cast<void*>(prototype->map())); | |
| 9897 } | |
| 9898 return !was_present; | |
| 9899 } | |
| 9900 | |
| 9901 | |
| 9902 // Can be called regardless of whether |user| was actually registered with | 9890 // Can be called regardless of whether |user| was actually registered with |
| 9903 // |prototype|. Returns true when there was a registration. | 9891 // |prototype|. Returns true when there was a registration. |
| 9904 // static | 9892 // static |
| 9905 bool JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype, | 9893 bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) { |
| 9906 Handle<HeapObject> user) { | 9894 DCHECK(user->is_prototype_map()); |
| 9907 Isolate* isolate = prototype->GetIsolate(); | 9895 // If it doesn't have a PrototypeInfo, it was never registered. |
| 9896 if (!user->prototype_info()->IsPrototypeInfo()) return false; |
| 9897 // If it doesn't have a prototype, it can't be registered. |
| 9898 if (!user->prototype()->IsJSObject()) return false; |
| 9899 Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate); |
| 9900 Handle<PrototypeInfo> user_info = |
| 9901 Map::GetOrCreatePrototypeInfo(user, isolate); |
| 9902 int slot = user_info->registry_slot(); |
| 9903 if (slot == PrototypeInfo::UNREGISTERED) return false; |
| 9908 if (prototype->IsJSGlobalProxy()) { | 9904 if (prototype->IsJSGlobalProxy()) { |
| 9909 PrototypeIterator iter(isolate, prototype); | 9905 PrototypeIterator iter(isolate, prototype); |
| 9910 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 9906 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| 9911 } | 9907 } |
| 9912 DCHECK(prototype->map()->is_prototype_map()); | 9908 DCHECK(prototype->map()->is_prototype_map()); |
| 9913 Object* maybe_proto_info = prototype->map()->prototype_info(); | 9909 Object* maybe_proto_info = prototype->map()->prototype_info(); |
| 9914 if (!maybe_proto_info->IsPrototypeInfo()) return false; | 9910 // User knows its registry slot, prototype info and user registry must exist. |
| 9911 DCHECK(maybe_proto_info->IsPrototypeInfo()); |
| 9915 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info), | 9912 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info), |
| 9916 isolate); | 9913 isolate); |
| 9917 Object* maybe_registry = proto_info->prototype_users(); | 9914 Object* maybe_registry = proto_info->prototype_users(); |
| 9918 if (!maybe_registry->IsWeakFixedArray()) return false; | 9915 DCHECK(maybe_registry->IsWeakFixedArray()); |
| 9919 bool result = WeakFixedArray::cast(maybe_registry)->Remove(user); | 9916 DCHECK(WeakFixedArray::cast(maybe_registry)->Get(slot) == *user); |
| 9920 if (FLAG_trace_prototype_users && result) { | 9917 WeakFixedArray::cast(maybe_registry)->Clear(slot); |
| 9918 if (FLAG_trace_prototype_users) { |
| 9921 PrintF("Unregistering %p as a user of prototype %p.\n", | 9919 PrintF("Unregistering %p as a user of prototype %p.\n", |
| 9922 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype)); | 9920 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype)); |
| 9923 } | 9921 } |
| 9924 return result; | 9922 return true; |
| 9925 } | 9923 } |
| 9926 | 9924 |
| 9927 | 9925 |
| 9928 static void InvalidatePrototypeChainsInternal(Map* map) { | 9926 static void InvalidatePrototypeChainsInternal(Map* map) { |
| 9929 if (!map->is_prototype_map()) return; | 9927 if (!map->is_prototype_map()) return; |
| 9930 if (FLAG_trace_prototype_users) { | 9928 if (FLAG_trace_prototype_users) { |
| 9931 PrintF("Invalidating prototype map %p 's cell\n", | 9929 PrintF("Invalidating prototype map %p 's cell\n", |
| 9932 reinterpret_cast<void*>(map)); | 9930 reinterpret_cast<void*>(map)); |
| 9933 } | 9931 } |
| 9934 Object* maybe_proto_info = map->prototype_info(); | 9932 Object* maybe_proto_info = map->prototype_info(); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9976 if (maybe_proto_info->IsPrototypeInfo()) { | 9974 if (maybe_proto_info->IsPrototypeInfo()) { |
| 9977 return handle(PrototypeInfo::cast(maybe_proto_info), isolate); | 9975 return handle(PrototypeInfo::cast(maybe_proto_info), isolate); |
| 9978 } | 9976 } |
| 9979 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo(); | 9977 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo(); |
| 9980 prototype->map()->set_prototype_info(*proto_info); | 9978 prototype->map()->set_prototype_info(*proto_info); |
| 9981 return proto_info; | 9979 return proto_info; |
| 9982 } | 9980 } |
| 9983 | 9981 |
| 9984 | 9982 |
| 9985 // static | 9983 // static |
| 9984 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<Map> prototype_map, |
| 9985 Isolate* isolate) { |
| 9986 Object* maybe_proto_info = prototype_map->prototype_info(); |
| 9987 if (maybe_proto_info->IsPrototypeInfo()) { |
| 9988 return handle(PrototypeInfo::cast(maybe_proto_info), isolate); |
| 9989 } |
| 9990 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo(); |
| 9991 prototype_map->set_prototype_info(*proto_info); |
| 9992 return proto_info; |
| 9993 } |
| 9994 |
| 9995 |
| 9996 // static |
| 9986 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, | 9997 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, |
| 9987 Isolate* isolate) { | 9998 Isolate* isolate) { |
| 9988 Handle<Object> maybe_prototype(map->prototype(), isolate); | 9999 Handle<Object> maybe_prototype(map->prototype(), isolate); |
| 9989 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null(); | 10000 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null(); |
| 9990 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype); | 10001 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype); |
| 9991 if (prototype->IsJSGlobalProxy()) { | 10002 if (prototype->IsJSGlobalProxy()) { |
| 9992 PrototypeIterator iter(isolate, prototype); | 10003 PrototypeIterator iter(isolate, prototype); |
| 9993 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 10004 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| 9994 } | 10005 } |
| 9995 // Ensure the prototype is registered with its own prototypes so its cell | 10006 // Ensure the prototype is registered with its own prototypes so its cell |
| (...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10466 WeakFixedArray* list = | 10477 WeakFixedArray* list = |
| 10467 WeakFixedArray::cast(old_script->shared_function_infos()); | 10478 WeakFixedArray::cast(old_script->shared_function_infos()); |
| 10468 list->Remove(shared); | 10479 list->Remove(shared); |
| 10469 } | 10480 } |
| 10470 } | 10481 } |
| 10471 // Add shared function info to new script's list. | 10482 // Add shared function info to new script's list. |
| 10472 if (script_object->IsScript()) { | 10483 if (script_object->IsScript()) { |
| 10473 Handle<Script> script = Handle<Script>::cast(script_object); | 10484 Handle<Script> script = Handle<Script>::cast(script_object); |
| 10474 Handle<Object> list(script->shared_function_infos(), shared->GetIsolate()); | 10485 Handle<Object> list(script->shared_function_infos(), shared->GetIsolate()); |
| 10475 #ifdef DEBUG | 10486 #ifdef DEBUG |
| 10476 bool found = false; | 10487 if (list->IsWeakFixedArray()) { |
| 10477 list = WeakFixedArray::Add(list, shared, WeakFixedArray::kAddIfNotFound, | 10488 Handle<WeakFixedArray> array = Handle<WeakFixedArray>::cast(list); |
| 10478 &found); | 10489 for (int i = 0; i < array->Length(); ++i) { |
| 10479 CHECK(!found); | 10490 DCHECK(array->Get(i) != *shared); |
| 10480 #else | 10491 } |
| 10481 list = WeakFixedArray::Add(list, shared, WeakFixedArray::kAlwaysAdd); | 10492 } |
| 10482 #endif // DEBUG | 10493 #endif // DEBUG |
| 10494 list = WeakFixedArray::Add(list, shared); |
| 10483 script->set_shared_function_infos(*list); | 10495 script->set_shared_function_infos(*list); |
| 10484 } | 10496 } |
| 10485 // Finally set new script. | 10497 // Finally set new script. |
| 10486 shared->set_script(*script_object); | 10498 shared->set_script(*script_object); |
| 10487 } | 10499 } |
| 10488 | 10500 |
| 10489 | 10501 |
| 10490 String* SharedFunctionInfo::DebugName() { | 10502 String* SharedFunctionInfo::DebugName() { |
| 10491 Object* n = name(); | 10503 Object* n = name(); |
| 10492 if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name(); | 10504 if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name(); |
| (...skipping 5658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16151 Handle<Object> new_value) { | 16163 Handle<Object> new_value) { |
| 16152 if (cell->value() != *new_value) { | 16164 if (cell->value() != *new_value) { |
| 16153 cell->set_value(*new_value); | 16165 cell->set_value(*new_value); |
| 16154 Isolate* isolate = cell->GetIsolate(); | 16166 Isolate* isolate = cell->GetIsolate(); |
| 16155 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16167 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 16156 isolate, DependentCode::kPropertyCellChangedGroup); | 16168 isolate, DependentCode::kPropertyCellChangedGroup); |
| 16157 } | 16169 } |
| 16158 } | 16170 } |
| 16159 } // namespace internal | 16171 } // namespace internal |
| 16160 } // namespace v8 | 16172 } // namespace v8 |
| OLD | NEW |