| 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 1877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1888 DCHECK(target_inobject < inobject_properties()); | 1888 DCHECK(target_inobject < inobject_properties()); |
| 1889 if (target_number_of_fields <= target_inobject) { | 1889 if (target_number_of_fields <= target_inobject) { |
| 1890 DCHECK(target_number_of_fields + target_unused == target_inobject); | 1890 DCHECK(target_number_of_fields + target_unused == target_inobject); |
| 1891 return false; | 1891 return false; |
| 1892 } | 1892 } |
| 1893 // Otherwise, properties will need to be moved to the backing store. | 1893 // Otherwise, properties will need to be moved to the backing store. |
| 1894 return true; | 1894 return true; |
| 1895 } | 1895 } |
| 1896 | 1896 |
| 1897 | 1897 |
| 1898 static void UpdatePrototypeUserRegistration(Handle<Map> old_map, |
| 1899 Handle<Map> new_map, |
| 1900 Isolate* isolate) { |
| 1901 if (!FLAG_track_prototype_users) return; |
| 1902 if (!old_map->is_prototype_map()) return; |
| 1903 DCHECK(new_map->is_prototype_map()); |
| 1904 bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate); |
| 1905 new_map->set_prototype_info(old_map->prototype_info()); |
| 1906 old_map->set_prototype_info(Smi::FromInt(0)); |
| 1907 if (FLAG_trace_prototype_users) { |
| 1908 PrintF("Moving prototype_info %p from map %p to map %p.\n", |
| 1909 reinterpret_cast<void*>(new_map->prototype_info()), |
| 1910 reinterpret_cast<void*>(*old_map), |
| 1911 reinterpret_cast<void*>(*new_map)); |
| 1912 } |
| 1913 if (was_registered) { |
| 1914 if (new_map->prototype_info()->IsPrototypeInfo()) { |
| 1915 // The new map isn't registered with its prototype yet; reflect this fact |
| 1916 // in the PrototypeInfo it just inherited from the old map. |
| 1917 PrototypeInfo::cast(new_map->prototype_info()) |
| 1918 ->set_registry_slot(PrototypeInfo::UNREGISTERED); |
| 1919 } |
| 1920 JSObject::LazyRegisterPrototypeUser(new_map, isolate); |
| 1921 } |
| 1922 } |
| 1923 |
| 1924 |
| 1898 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, | 1925 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, |
| 1899 int expected_additional_properties) { | 1926 int expected_additional_properties) { |
| 1900 if (object->map() == *new_map) return; | 1927 if (object->map() == *new_map) return; |
| 1901 // If this object is a prototype (the callee will check), invalidate any | 1928 // If this object is a prototype (the callee will check), invalidate any |
| 1902 // prototype chains involving it. | 1929 // prototype chains involving it. |
| 1903 InvalidatePrototypeChains(object->map()); | 1930 InvalidatePrototypeChains(object->map()); |
| 1904 Handle<Map> old_map(object->map()); | 1931 Handle<Map> old_map(object->map()); |
| 1905 | 1932 |
| 1906 // If the map was registered with its prototype before, ensure that it | 1933 // If the map was registered with its prototype before, ensure that it |
| 1907 // registers with its new prototype now. This preserves the invariant that | 1934 // registers with its new prototype now. This preserves the invariant that |
| 1908 // when a map on a prototype chain is registered with its prototype, then | 1935 // when a map on a prototype chain is registered with its prototype, then |
| 1909 // all prototypes further up the chain are also registered with their | 1936 // all prototypes further up the chain are also registered with their |
| 1910 // respective prototypes. | 1937 // respective prototypes. |
| 1911 Object* maybe_old_prototype = old_map->prototype(); | 1938 UpdatePrototypeUserRegistration(old_map, new_map, new_map->GetIsolate()); |
| 1912 if (FLAG_track_prototype_users && old_map->is_prototype_map() && | |
| 1913 maybe_old_prototype->IsJSObject()) { | |
| 1914 Handle<JSObject> old_prototype(JSObject::cast(maybe_old_prototype)); | |
| 1915 bool was_registered = | |
| 1916 JSObject::UnregisterPrototypeUser(old_prototype, old_map); | |
| 1917 if (was_registered) { | |
| 1918 JSObject::LazyRegisterPrototypeUser(new_map, new_map->GetIsolate()); | |
| 1919 } | |
| 1920 } | |
| 1921 | 1939 |
| 1922 if (object->HasFastProperties()) { | 1940 if (object->HasFastProperties()) { |
| 1923 if (!new_map->is_dictionary_map()) { | 1941 if (!new_map->is_dictionary_map()) { |
| 1924 MigrateFastToFast(object, new_map); | 1942 MigrateFastToFast(object, new_map); |
| 1925 if (old_map->is_prototype_map()) { | 1943 if (old_map->is_prototype_map()) { |
| 1926 // Clear out the old descriptor array to avoid problems to sharing | 1944 // Clear out the old descriptor array to avoid problems to sharing |
| 1927 // the descriptor array without using an explicit. | 1945 // the descriptor array without using an explicit. |
| 1928 old_map->InitializeDescriptors( | 1946 old_map->InitializeDescriptors( |
| 1929 old_map->GetHeap()->empty_descriptor_array(), | 1947 old_map->GetHeap()->empty_descriptor_array(), |
| 1930 LayoutDescriptor::FastPointerLayout()); | 1948 LayoutDescriptor::FastPointerLayout()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1943 | 1961 |
| 1944 // Slow-to-slow migration is trivial. | 1962 // Slow-to-slow migration is trivial. |
| 1945 object->set_map(*new_map); | 1963 object->set_map(*new_map); |
| 1946 } | 1964 } |
| 1947 | 1965 |
| 1948 // Careful: Don't allocate here! | 1966 // Careful: Don't allocate here! |
| 1949 // For some callers of this method, |object| might be in an inconsistent | 1967 // For some callers of this method, |object| might be in an inconsistent |
| 1950 // state now: the new map might have a new elements_kind, but the object's | 1968 // state now: the new map might have a new elements_kind, but the object's |
| 1951 // elements pointer hasn't been updated yet. Callers will fix this, but in | 1969 // elements pointer hasn't been updated yet. Callers will fix this, but in |
| 1952 // the meantime, (indirectly) calling JSObjectVerify() must be avoided. | 1970 // the meantime, (indirectly) calling JSObjectVerify() must be avoided. |
| 1953 DisallowHeapAllocation no_object_verification; | 1971 // When adding code here, add a DisallowHeapAllocation too. |
| 1954 | |
| 1955 if (old_map->is_prototype_map() && FLAG_track_prototype_users) { | |
| 1956 DCHECK(new_map->is_prototype_map()); | |
| 1957 DCHECK(object->map() == *new_map); | |
| 1958 new_map->set_prototype_info(old_map->prototype_info()); | |
| 1959 old_map->set_prototype_info(Smi::FromInt(0)); | |
| 1960 if (FLAG_trace_prototype_users) { | |
| 1961 PrintF("Moving prototype_info %p from map %p to map %p.\n", | |
| 1962 reinterpret_cast<void*>(new_map->prototype_info()), | |
| 1963 reinterpret_cast<void*>(*old_map), | |
| 1964 reinterpret_cast<void*>(*new_map)); | |
| 1965 } | |
| 1966 } | |
| 1967 } | 1972 } |
| 1968 | 1973 |
| 1969 | 1974 |
| 1970 // To migrate a fast instance to a fast map: | 1975 // To migrate a fast instance to a fast map: |
| 1971 // - First check whether the instance needs to be rewritten. If not, simply | 1976 // - First check whether the instance needs to be rewritten. If not, simply |
| 1972 // change the map. | 1977 // change the map. |
| 1973 // - Otherwise, allocate a fixed array large enough to hold all fields, in | 1978 // - Otherwise, allocate a fixed array large enough to hold all fields, in |
| 1974 // addition to unused space. | 1979 // addition to unused space. |
| 1975 // - Copy all existing properties in, in the following order: backing store | 1980 // - Copy all existing properties in, in the following order: backing store |
| 1976 // properties, unused fields, inobject properties. | 1981 // properties, unused fields, inobject properties. |
| (...skipping 2785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4762 } | 4767 } |
| 4763 | 4768 |
| 4764 Handle<Map> old_map(object->map(), isolate); | 4769 Handle<Map> old_map(object->map(), isolate); |
| 4765 | 4770 |
| 4766 int inobject_props = old_map->inobject_properties(); | 4771 int inobject_props = old_map->inobject_properties(); |
| 4767 | 4772 |
| 4768 // Allocate new map. | 4773 // Allocate new map. |
| 4769 Handle<Map> new_map = Map::CopyDropDescriptors(old_map); | 4774 Handle<Map> new_map = Map::CopyDropDescriptors(old_map); |
| 4770 new_map->set_dictionary_map(false); | 4775 new_map->set_dictionary_map(false); |
| 4771 | 4776 |
| 4772 if (old_map->is_prototype_map() && FLAG_track_prototype_users) { | 4777 UpdatePrototypeUserRegistration(old_map, new_map, isolate); |
| 4773 DCHECK(new_map->is_prototype_map()); | |
| 4774 | |
| 4775 Object* maybe_old_prototype = old_map->prototype(); | |
| 4776 if (maybe_old_prototype->IsJSObject()) { | |
| 4777 Handle<JSObject> old_prototype(JSObject::cast(maybe_old_prototype)); | |
| 4778 bool was_registered = | |
| 4779 JSObject::UnregisterPrototypeUser(old_prototype, old_map); | |
| 4780 if (was_registered) { | |
| 4781 JSObject::LazyRegisterPrototypeUser(new_map, isolate); | |
| 4782 } | |
| 4783 } | |
| 4784 new_map->set_prototype_info(old_map->prototype_info()); | |
| 4785 old_map->set_prototype_info(Smi::FromInt(0)); | |
| 4786 if (FLAG_trace_prototype_users) { | |
| 4787 PrintF("Moving prototype_info %p from map %p to map %p.\n", | |
| 4788 reinterpret_cast<void*>(new_map->prototype_info()), | |
| 4789 reinterpret_cast<void*>(*old_map), | |
| 4790 reinterpret_cast<void*>(*new_map)); | |
| 4791 } | |
| 4792 } | |
| 4793 | 4778 |
| 4794 #if TRACE_MAPS | 4779 #if TRACE_MAPS |
| 4795 if (FLAG_trace_maps) { | 4780 if (FLAG_trace_maps) { |
| 4796 PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n", | 4781 PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n", |
| 4797 reinterpret_cast<void*>(*old_map), reinterpret_cast<void*>(*new_map), | 4782 reinterpret_cast<void*>(*old_map), reinterpret_cast<void*>(*new_map), |
| 4798 reason); | 4783 reason); |
| 4799 } | 4784 } |
| 4800 #endif | 4785 #endif |
| 4801 | 4786 |
| 4802 if (instance_descriptor_length == 0) { | 4787 if (instance_descriptor_length == 0) { |
| (...skipping 3128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7931 : array->GetIsolate()->factory()->NewWeakCell(value); | 7916 : array->GetIsolate()->factory()->NewWeakCell(value); |
| 7932 Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell); | 7917 Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell); |
| 7933 if (FLAG_trace_weak_arrays) { | 7918 if (FLAG_trace_weak_arrays) { |
| 7934 PrintF("[WeakFixedArray: storing at index %d ]\n", index); | 7919 PrintF("[WeakFixedArray: storing at index %d ]\n", index); |
| 7935 } | 7920 } |
| 7936 array->set_last_used_index(index); | 7921 array->set_last_used_index(index); |
| 7937 } | 7922 } |
| 7938 | 7923 |
| 7939 | 7924 |
| 7940 // static | 7925 // static |
| 7941 Handle<WeakFixedArray> WeakFixedArray::Add( | 7926 Handle<WeakFixedArray> WeakFixedArray::Add(Handle<Object> maybe_array, |
| 7942 Handle<Object> maybe_array, Handle<HeapObject> value, | 7927 Handle<HeapObject> value, |
| 7943 SearchForDuplicates search_for_duplicates, bool* was_present) { | 7928 int* assigned_index) { |
| 7944 Handle<WeakFixedArray> array = | 7929 Handle<WeakFixedArray> array = |
| 7945 (maybe_array.is_null() || !maybe_array->IsWeakFixedArray()) | 7930 (maybe_array.is_null() || !maybe_array->IsWeakFixedArray()) |
| 7946 ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null()) | 7931 ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null()) |
| 7947 : Handle<WeakFixedArray>::cast(maybe_array); | 7932 : Handle<WeakFixedArray>::cast(maybe_array); |
| 7948 if (was_present != NULL) *was_present = false; | |
| 7949 if (search_for_duplicates == kAddIfNotFound) { | |
| 7950 for (int i = 0; i < array->Length(); ++i) { | |
| 7951 if (array->Get(i) == *value) { | |
| 7952 if (was_present != NULL) *was_present = true; | |
| 7953 return array; | |
| 7954 } | |
| 7955 } | |
| 7956 #if 0 // Enable this if you want to check your search_for_duplicates flags. | |
| 7957 } else { | |
| 7958 for (int i = 0; i < array->Length(); ++i) { | |
| 7959 DCHECK_NE(*value, array->Get(i)); | |
| 7960 } | |
| 7961 #endif | |
| 7962 } | |
| 7963 | |
| 7964 // Try to store the new entry if there's room. Optimize for consecutive | 7933 // Try to store the new entry if there's room. Optimize for consecutive |
| 7965 // accesses. | 7934 // accesses. |
| 7966 int first_index = array->last_used_index(); | 7935 int first_index = array->last_used_index(); |
| 7967 if (array->Length() > 0) { | 7936 int length = array->Length(); |
| 7937 if (length > 0) { |
| 7968 for (int i = first_index;;) { | 7938 for (int i = first_index;;) { |
| 7969 if (array->IsEmptySlot((i))) { | 7939 if (array->IsEmptySlot((i))) { |
| 7970 WeakFixedArray::Set(array, i, value); | 7940 WeakFixedArray::Set(array, i, value); |
| 7941 if (assigned_index != NULL) *assigned_index = i; |
| 7971 return array; | 7942 return array; |
| 7972 } | 7943 } |
| 7973 if (FLAG_trace_weak_arrays) { | 7944 if (FLAG_trace_weak_arrays) { |
| 7974 PrintF("[WeakFixedArray: searching for free slot]\n"); | 7945 PrintF("[WeakFixedArray: searching for free slot]\n"); |
| 7975 } | 7946 } |
| 7976 i = (i + 1) % array->Length(); | 7947 i = (i + 1) % length; |
| 7977 if (i == first_index) break; | 7948 if (i == first_index) break; |
| 7978 } | 7949 } |
| 7979 } | 7950 } |
| 7980 | 7951 |
| 7981 // No usable slot found, grow the array. | 7952 // No usable slot found, grow the array. |
| 7982 int new_length = | 7953 int new_length = length == 0 ? 1 : length + (length >> 1) + 4; |
| 7983 array->Length() == 0 ? 1 : array->Length() + (array->Length() >> 1) + 4; | |
| 7984 Handle<WeakFixedArray> new_array = | 7954 Handle<WeakFixedArray> new_array = |
| 7985 Allocate(array->GetIsolate(), new_length, array); | 7955 Allocate(array->GetIsolate(), new_length, array); |
| 7986 if (FLAG_trace_weak_arrays) { | 7956 if (FLAG_trace_weak_arrays) { |
| 7987 PrintF("[WeakFixedArray: growing to size %d ]\n", new_length); | 7957 PrintF("[WeakFixedArray: growing to size %d ]\n", new_length); |
| 7988 } | 7958 } |
| 7989 WeakFixedArray::Set(new_array, array->Length(), value); | 7959 WeakFixedArray::Set(new_array, length, value); |
| 7960 if (assigned_index != NULL) *assigned_index = length; |
| 7990 return new_array; | 7961 return new_array; |
| 7991 } | 7962 } |
| 7992 | 7963 |
| 7993 | 7964 |
| 7965 template <class CompactionCallback> |
| 7994 void WeakFixedArray::Compact() { | 7966 void WeakFixedArray::Compact() { |
| 7995 FixedArray* array = FixedArray::cast(this); | 7967 FixedArray* array = FixedArray::cast(this); |
| 7996 int new_length = kFirstIndex; | 7968 int new_length = kFirstIndex; |
| 7997 for (int i = kFirstIndex; i < array->length(); i++) { | 7969 for (int i = kFirstIndex; i < array->length(); i++) { |
| 7998 Object* element = array->get(i); | 7970 Object* element = array->get(i); |
| 7999 if (element->IsSmi()) continue; | 7971 if (element->IsSmi()) continue; |
| 8000 if (WeakCell::cast(element)->cleared()) continue; | 7972 if (WeakCell::cast(element)->cleared()) continue; |
| 7973 Object* value = WeakCell::cast(element)->value(); |
| 7974 CompactionCallback::Callback(value, i - kFirstIndex, |
| 7975 new_length - kFirstIndex); |
| 8001 array->set(new_length++, element); | 7976 array->set(new_length++, element); |
| 8002 } | 7977 } |
| 8003 array->Shrink(new_length); | 7978 array->Shrink(new_length); |
| 8004 set_last_used_index(0); | 7979 set_last_used_index(0); |
| 8005 } | 7980 } |
| 8006 | 7981 |
| 8007 | 7982 |
| 7983 void JSObject::PrototypeRegistryCompactionCallback::Callback(Object* value, |
| 7984 int old_index, |
| 7985 int new_index) { |
| 7986 DCHECK(value->IsMap() && Map::cast(value)->is_prototype_map()); |
| 7987 Map* map = Map::cast(value); |
| 7988 DCHECK(map->prototype_info()->IsPrototypeInfo()); |
| 7989 PrototypeInfo* proto_info = PrototypeInfo::cast(map->prototype_info()); |
| 7990 DCHECK_EQ(old_index, proto_info->registry_slot()); |
| 7991 proto_info->set_registry_slot(new_index); |
| 7992 } |
| 7993 |
| 7994 |
| 7995 template void WeakFixedArray::Compact<WeakFixedArray::NullCallback>(); |
| 7996 template void |
| 7997 WeakFixedArray::Compact<JSObject::PrototypeRegistryCompactionCallback>(); |
| 7998 |
| 7999 |
| 8008 bool WeakFixedArray::Remove(Handle<HeapObject> value) { | 8000 bool WeakFixedArray::Remove(Handle<HeapObject> value) { |
| 8009 if (Length() == 0) return false; | 8001 if (Length() == 0) return false; |
| 8010 // Optimize for the most recently added element to be removed again. | 8002 // Optimize for the most recently added element to be removed again. |
| 8011 int first_index = last_used_index(); | 8003 int first_index = last_used_index(); |
| 8012 for (int i = first_index;;) { | 8004 for (int i = first_index;;) { |
| 8013 if (Get(i) == *value) { | 8005 if (Get(i) == *value) { |
| 8014 Clear(i); | 8006 Clear(i); |
| 8015 // Users of WeakFixedArray should make sure that there are no duplicates, | 8007 // Users of WeakFixedArray should make sure that there are no duplicates. |
| 8016 // they can use Add(..., kAddIfNotFound) if necessary. | |
| 8017 return true; | 8008 return true; |
| 8018 } | 8009 } |
| 8019 i = (i + 1) % Length(); | 8010 i = (i + 1) % Length(); |
| 8020 if (i == first_index) return false; | 8011 if (i == first_index) return false; |
| 8021 } | 8012 } |
| 8022 UNREACHABLE(); | 8013 UNREACHABLE(); |
| 8023 } | 8014 } |
| 8024 | 8015 |
| 8025 | 8016 |
| 8026 // static | 8017 // static |
| (...skipping 1724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9751 | 9742 |
| 9752 | 9743 |
| 9753 // static | 9744 // static |
| 9754 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) { | 9745 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) { |
| 9755 DCHECK(FLAG_track_prototype_users); | 9746 DCHECK(FLAG_track_prototype_users); |
| 9756 // Contract: In line with InvalidatePrototypeChains()'s requirements, | 9747 // Contract: In line with InvalidatePrototypeChains()'s requirements, |
| 9757 // leaf maps don't need to register as users, only prototypes do. | 9748 // leaf maps don't need to register as users, only prototypes do. |
| 9758 DCHECK(user->is_prototype_map()); | 9749 DCHECK(user->is_prototype_map()); |
| 9759 | 9750 |
| 9760 Handle<Map> current_user = user; | 9751 Handle<Map> current_user = user; |
| 9752 Handle<PrototypeInfo> current_user_info = |
| 9753 Map::GetOrCreatePrototypeInfo(user, isolate); |
| 9761 for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) { | 9754 for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) { |
| 9755 // Walk up the prototype chain as far as links haven't been registered yet. |
| 9756 if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) { |
| 9757 break; |
| 9758 } |
| 9762 Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter); | 9759 Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter); |
| 9763 if (maybe_proto->IsJSGlobalProxy()) continue; | 9760 if (maybe_proto->IsJSGlobalProxy()) continue; |
| 9764 // Proxies on the prototype chain are not supported. | 9761 // Proxies on the prototype chain are not supported. |
| 9765 if (maybe_proto->IsJSProxy()) return; | 9762 if (maybe_proto->IsJSProxy()) return; |
| 9766 Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto); | 9763 Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto); |
| 9767 bool just_registered = | 9764 Handle<PrototypeInfo> proto_info = |
| 9768 RegisterPrototypeUserIfNotRegistered(proto, current_user, isolate); | 9765 Map::GetOrCreatePrototypeInfo(proto, isolate); |
| 9769 // Walk up the prototype chain as far as links haven't been registered yet. | 9766 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate); |
| 9770 if (!just_registered) break; | 9767 int slot = 0; |
| 9768 Handle<WeakFixedArray> new_array = |
| 9769 WeakFixedArray::Add(maybe_registry, current_user, &slot); |
| 9770 current_user_info->set_registry_slot(slot); |
| 9771 if (!maybe_registry.is_identical_to(new_array)) { |
| 9772 proto_info->set_prototype_users(*new_array); |
| 9773 } |
| 9774 if (FLAG_trace_prototype_users) { |
| 9775 PrintF("Registering %p as a user of prototype %p (map=%p).\n", |
| 9776 reinterpret_cast<void*>(*current_user), |
| 9777 reinterpret_cast<void*>(*proto), |
| 9778 reinterpret_cast<void*>(proto->map())); |
| 9779 } |
| 9780 |
| 9771 current_user = handle(proto->map(), isolate); | 9781 current_user = handle(proto->map(), isolate); |
| 9782 current_user_info = proto_info; |
| 9772 } | 9783 } |
| 9773 } | 9784 } |
| 9774 | 9785 |
| 9775 | 9786 |
| 9776 // Returns true if the user was not yet registered. | |
| 9777 // static | |
| 9778 bool JSObject::RegisterPrototypeUserIfNotRegistered(Handle<JSObject> prototype, | |
| 9779 Handle<HeapObject> user, | |
| 9780 Isolate* isolate) { | |
| 9781 Handle<PrototypeInfo> proto_info = | |
| 9782 Map::GetOrCreatePrototypeInfo(prototype, isolate); | |
| 9783 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate); | |
| 9784 bool was_present = false; | |
| 9785 Handle<WeakFixedArray> new_array = WeakFixedArray::Add( | |
| 9786 maybe_registry, user, WeakFixedArray::kAddIfNotFound, &was_present); | |
| 9787 if (!maybe_registry.is_identical_to(new_array)) { | |
| 9788 proto_info->set_prototype_users(*new_array); | |
| 9789 } | |
| 9790 if (FLAG_trace_prototype_users && !was_present) { | |
| 9791 PrintF("Registering %p as a user of prototype %p (map=%p).\n", | |
| 9792 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype), | |
| 9793 reinterpret_cast<void*>(prototype->map())); | |
| 9794 } | |
| 9795 return !was_present; | |
| 9796 } | |
| 9797 | |
| 9798 | |
| 9799 // Can be called regardless of whether |user| was actually registered with | 9787 // Can be called regardless of whether |user| was actually registered with |
| 9800 // |prototype|. Returns true when there was a registration. | 9788 // |prototype|. Returns true when there was a registration. |
| 9801 // static | 9789 // static |
| 9802 bool JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype, | 9790 bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) { |
| 9803 Handle<HeapObject> user) { | 9791 DCHECK(user->is_prototype_map()); |
| 9804 Isolate* isolate = prototype->GetIsolate(); | 9792 // If it doesn't have a PrototypeInfo, it was never registered. |
| 9793 if (!user->prototype_info()->IsPrototypeInfo()) return false; |
| 9794 // If it doesn't have a prototype, it can't be registered. |
| 9795 if (!user->prototype()->IsJSObject()) return false; |
| 9796 Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate); |
| 9797 Handle<PrototypeInfo> user_info = |
| 9798 Map::GetOrCreatePrototypeInfo(user, isolate); |
| 9799 int slot = user_info->registry_slot(); |
| 9800 if (slot == PrototypeInfo::UNREGISTERED) return false; |
| 9805 if (prototype->IsJSGlobalProxy()) { | 9801 if (prototype->IsJSGlobalProxy()) { |
| 9806 PrototypeIterator iter(isolate, prototype); | 9802 PrototypeIterator iter(isolate, prototype); |
| 9807 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 9803 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| 9808 } | 9804 } |
| 9809 DCHECK(prototype->map()->is_prototype_map()); | 9805 DCHECK(prototype->map()->is_prototype_map()); |
| 9810 Object* maybe_proto_info = prototype->map()->prototype_info(); | 9806 Object* maybe_proto_info = prototype->map()->prototype_info(); |
| 9811 if (!maybe_proto_info->IsPrototypeInfo()) return false; | 9807 // User knows its registry slot, prototype info and user registry must exist. |
| 9808 DCHECK(maybe_proto_info->IsPrototypeInfo()); |
| 9812 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info), | 9809 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info), |
| 9813 isolate); | 9810 isolate); |
| 9814 Object* maybe_registry = proto_info->prototype_users(); | 9811 Object* maybe_registry = proto_info->prototype_users(); |
| 9815 if (!maybe_registry->IsWeakFixedArray()) return false; | 9812 DCHECK(maybe_registry->IsWeakFixedArray()); |
| 9816 bool result = WeakFixedArray::cast(maybe_registry)->Remove(user); | 9813 DCHECK(WeakFixedArray::cast(maybe_registry)->Get(slot) == *user); |
| 9817 if (FLAG_trace_prototype_users && result) { | 9814 WeakFixedArray::cast(maybe_registry)->Clear(slot); |
| 9815 if (FLAG_trace_prototype_users) { |
| 9818 PrintF("Unregistering %p as a user of prototype %p.\n", | 9816 PrintF("Unregistering %p as a user of prototype %p.\n", |
| 9819 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype)); | 9817 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype)); |
| 9820 } | 9818 } |
| 9821 return result; | 9819 return true; |
| 9822 } | 9820 } |
| 9823 | 9821 |
| 9824 | 9822 |
| 9825 static void InvalidatePrototypeChainsInternal(Map* map) { | 9823 static void InvalidatePrototypeChainsInternal(Map* map) { |
| 9826 if (!map->is_prototype_map()) return; | 9824 if (!map->is_prototype_map()) return; |
| 9827 if (FLAG_trace_prototype_users) { | 9825 if (FLAG_trace_prototype_users) { |
| 9828 PrintF("Invalidating prototype map %p 's cell\n", | 9826 PrintF("Invalidating prototype map %p 's cell\n", |
| 9829 reinterpret_cast<void*>(map)); | 9827 reinterpret_cast<void*>(map)); |
| 9830 } | 9828 } |
| 9831 Object* maybe_proto_info = map->prototype_info(); | 9829 Object* maybe_proto_info = map->prototype_info(); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9873 if (maybe_proto_info->IsPrototypeInfo()) { | 9871 if (maybe_proto_info->IsPrototypeInfo()) { |
| 9874 return handle(PrototypeInfo::cast(maybe_proto_info), isolate); | 9872 return handle(PrototypeInfo::cast(maybe_proto_info), isolate); |
| 9875 } | 9873 } |
| 9876 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo(); | 9874 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo(); |
| 9877 prototype->map()->set_prototype_info(*proto_info); | 9875 prototype->map()->set_prototype_info(*proto_info); |
| 9878 return proto_info; | 9876 return proto_info; |
| 9879 } | 9877 } |
| 9880 | 9878 |
| 9881 | 9879 |
| 9882 // static | 9880 // static |
| 9881 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<Map> prototype_map, |
| 9882 Isolate* isolate) { |
| 9883 Object* maybe_proto_info = prototype_map->prototype_info(); |
| 9884 if (maybe_proto_info->IsPrototypeInfo()) { |
| 9885 return handle(PrototypeInfo::cast(maybe_proto_info), isolate); |
| 9886 } |
| 9887 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo(); |
| 9888 prototype_map->set_prototype_info(*proto_info); |
| 9889 return proto_info; |
| 9890 } |
| 9891 |
| 9892 |
| 9893 // static |
| 9883 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, | 9894 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, |
| 9884 Isolate* isolate) { | 9895 Isolate* isolate) { |
| 9885 Handle<Object> maybe_prototype(map->prototype(), isolate); | 9896 Handle<Object> maybe_prototype(map->prototype(), isolate); |
| 9886 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null(); | 9897 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null(); |
| 9887 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype); | 9898 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype); |
| 9888 if (prototype->IsJSGlobalProxy()) { | 9899 if (prototype->IsJSGlobalProxy()) { |
| 9889 PrototypeIterator iter(isolate, prototype); | 9900 PrototypeIterator iter(isolate, prototype); |
| 9890 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 9901 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| 9891 } | 9902 } |
| 9892 // Ensure the prototype is registered with its own prototypes so its cell | 9903 // 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... |
| 10363 WeakFixedArray* list = | 10374 WeakFixedArray* list = |
| 10364 WeakFixedArray::cast(old_script->shared_function_infos()); | 10375 WeakFixedArray::cast(old_script->shared_function_infos()); |
| 10365 list->Remove(shared); | 10376 list->Remove(shared); |
| 10366 } | 10377 } |
| 10367 } | 10378 } |
| 10368 // Add shared function info to new script's list. | 10379 // Add shared function info to new script's list. |
| 10369 if (script_object->IsScript()) { | 10380 if (script_object->IsScript()) { |
| 10370 Handle<Script> script = Handle<Script>::cast(script_object); | 10381 Handle<Script> script = Handle<Script>::cast(script_object); |
| 10371 Handle<Object> list(script->shared_function_infos(), shared->GetIsolate()); | 10382 Handle<Object> list(script->shared_function_infos(), shared->GetIsolate()); |
| 10372 #ifdef DEBUG | 10383 #ifdef DEBUG |
| 10373 bool found = false; | 10384 if (list->IsWeakFixedArray()) { |
| 10374 list = WeakFixedArray::Add(list, shared, WeakFixedArray::kAddIfNotFound, | 10385 Handle<WeakFixedArray> array = Handle<WeakFixedArray>::cast(list); |
| 10375 &found); | 10386 for (int i = 0; i < array->Length(); ++i) { |
| 10376 CHECK(!found); | 10387 DCHECK(array->Get(i) != *shared); |
| 10377 #else | 10388 } |
| 10378 list = WeakFixedArray::Add(list, shared, WeakFixedArray::kAlwaysAdd); | 10389 } |
| 10379 #endif // DEBUG | 10390 #endif // DEBUG |
| 10391 list = WeakFixedArray::Add(list, shared); |
| 10380 script->set_shared_function_infos(*list); | 10392 script->set_shared_function_infos(*list); |
| 10381 } | 10393 } |
| 10382 // Finally set new script. | 10394 // Finally set new script. |
| 10383 shared->set_script(*script_object); | 10395 shared->set_script(*script_object); |
| 10384 } | 10396 } |
| 10385 | 10397 |
| 10386 | 10398 |
| 10387 String* SharedFunctionInfo::DebugName() { | 10399 String* SharedFunctionInfo::DebugName() { |
| 10388 Object* n = name(); | 10400 Object* n = name(); |
| 10389 if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name(); | 10401 if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name(); |
| (...skipping 5479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15869 if (cell->value() != *new_value) { | 15881 if (cell->value() != *new_value) { |
| 15870 cell->set_value(*new_value); | 15882 cell->set_value(*new_value); |
| 15871 Isolate* isolate = cell->GetIsolate(); | 15883 Isolate* isolate = cell->GetIsolate(); |
| 15872 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 15884 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 15873 isolate, DependentCode::kPropertyCellChangedGroup); | 15885 isolate, DependentCode::kPropertyCellChangedGroup); |
| 15874 } | 15886 } |
| 15875 } | 15887 } |
| 15876 | 15888 |
| 15877 } // namespace internal | 15889 } // namespace internal |
| 15878 } // namespace v8 | 15890 } // namespace v8 |
| OLD | NEW |