| 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 1893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1904 } | 1904 } |
| 1905 | 1905 |
| 1906 | 1906 |
| 1907 void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) { | 1907 void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) { |
| 1908 Isolate* isolate = parent->GetIsolate(); | 1908 Isolate* isolate = parent->GetIsolate(); |
| 1909 Handle<Name> name = isolate->factory()->elements_transition_symbol(); | 1909 Handle<Name> name = isolate->factory()->elements_transition_symbol(); |
| 1910 ConnectTransition(parent, child, name, SPECIAL_TRANSITION); | 1910 ConnectTransition(parent, child, name, SPECIAL_TRANSITION); |
| 1911 } | 1911 } |
| 1912 | 1912 |
| 1913 | 1913 |
| 1914 static void UpdatePrototypeUserRegistration(Handle<Map> old_map, |
| 1915 Handle<Map> new_map, |
| 1916 Isolate* isolate) { |
| 1917 if (!FLAG_track_prototype_users) return; |
| 1918 if (!old_map->is_prototype_map()) return; |
| 1919 DCHECK(new_map->is_prototype_map()); |
| 1920 bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate); |
| 1921 new_map->set_prototype_info(old_map->prototype_info()); |
| 1922 old_map->set_prototype_info(Smi::FromInt(0)); |
| 1923 if (FLAG_trace_prototype_users) { |
| 1924 PrintF("Moving prototype_info %p from map %p to map %p.\n", |
| 1925 reinterpret_cast<void*>(new_map->prototype_info()), |
| 1926 reinterpret_cast<void*>(*old_map), |
| 1927 reinterpret_cast<void*>(*new_map)); |
| 1928 } |
| 1929 if (was_registered) { |
| 1930 if (new_map->prototype_info()->IsPrototypeInfo()) { |
| 1931 // The new map isn't registered with its prototype yet; reflect this fact |
| 1932 // in the PrototypeInfo it just inherited from the old map. |
| 1933 PrototypeInfo::cast(new_map->prototype_info()) |
| 1934 ->set_registry_slot(PrototypeInfo::UNREGISTERED); |
| 1935 } |
| 1936 JSObject::LazyRegisterPrototypeUser(new_map, isolate); |
| 1937 } |
| 1938 } |
| 1939 |
| 1940 |
| 1914 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, | 1941 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, |
| 1915 int expected_additional_properties) { | 1942 int expected_additional_properties) { |
| 1916 if (object->map() == *new_map) return; | 1943 if (object->map() == *new_map) return; |
| 1917 // If this object is a prototype (the callee will check), invalidate any | 1944 // If this object is a prototype (the callee will check), invalidate any |
| 1918 // prototype chains involving it. | 1945 // prototype chains involving it. |
| 1919 InvalidatePrototypeChains(object->map()); | 1946 InvalidatePrototypeChains(object->map()); |
| 1920 Handle<Map> old_map(object->map()); | 1947 Handle<Map> old_map(object->map()); |
| 1921 | 1948 |
| 1922 // If the map was registered with its prototype before, ensure that it | 1949 // If the map was registered with its prototype before, ensure that it |
| 1923 // registers with its new prototype now. This preserves the invariant that | 1950 // registers with its new prototype now. This preserves the invariant that |
| 1924 // when a map on a prototype chain is registered with its prototype, then | 1951 // when a map on a prototype chain is registered with its prototype, then |
| 1925 // all prototypes further up the chain are also registered with their | 1952 // all prototypes further up the chain are also registered with their |
| 1926 // respective prototypes. | 1953 // respective prototypes. |
| 1927 Object* maybe_old_prototype = old_map->prototype(); | 1954 UpdatePrototypeUserRegistration(old_map, new_map, new_map->GetIsolate()); |
| 1928 if (FLAG_track_prototype_users && old_map->is_prototype_map() && | |
| 1929 maybe_old_prototype->IsJSObject()) { | |
| 1930 Handle<JSObject> old_prototype(JSObject::cast(maybe_old_prototype)); | |
| 1931 bool was_registered = | |
| 1932 JSObject::UnregisterPrototypeUser(old_prototype, old_map); | |
| 1933 if (was_registered) { | |
| 1934 JSObject::LazyRegisterPrototypeUser(new_map, new_map->GetIsolate()); | |
| 1935 } | |
| 1936 } | |
| 1937 | 1955 |
| 1938 if (object->HasFastProperties()) { | 1956 if (object->HasFastProperties()) { |
| 1939 if (!new_map->is_dictionary_map()) { | 1957 if (!new_map->is_dictionary_map()) { |
| 1940 MigrateFastToFast(object, new_map); | 1958 MigrateFastToFast(object, new_map); |
| 1941 if (old_map->is_prototype_map()) { | 1959 if (old_map->is_prototype_map()) { |
| 1942 // Clear out the old descriptor array to avoid problems to sharing | 1960 // Clear out the old descriptor array to avoid problems to sharing |
| 1943 // the descriptor array without using an explicit. | 1961 // the descriptor array without using an explicit. |
| 1944 old_map->InitializeDescriptors( | 1962 old_map->InitializeDescriptors( |
| 1945 old_map->GetHeap()->empty_descriptor_array(), | 1963 old_map->GetHeap()->empty_descriptor_array(), |
| 1946 LayoutDescriptor::FastPointerLayout()); | 1964 LayoutDescriptor::FastPointerLayout()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1959 | 1977 |
| 1960 // Slow-to-slow migration is trivial. | 1978 // Slow-to-slow migration is trivial. |
| 1961 object->set_map(*new_map); | 1979 object->set_map(*new_map); |
| 1962 } | 1980 } |
| 1963 | 1981 |
| 1964 // Careful: Don't allocate here! | 1982 // Careful: Don't allocate here! |
| 1965 // For some callers of this method, |object| might be in an inconsistent | 1983 // For some callers of this method, |object| might be in an inconsistent |
| 1966 // state now: the new map might have a new elements_kind, but the object's | 1984 // state now: the new map might have a new elements_kind, but the object's |
| 1967 // elements pointer hasn't been updated yet. Callers will fix this, but in | 1985 // elements pointer hasn't been updated yet. Callers will fix this, but in |
| 1968 // the meantime, (indirectly) calling JSObjectVerify() must be avoided. | 1986 // the meantime, (indirectly) calling JSObjectVerify() must be avoided. |
| 1969 DisallowHeapAllocation no_object_verification; | 1987 // When adding code here, add a DisallowHeapAllocation too. |
| 1970 | |
| 1971 if (old_map->is_prototype_map() && FLAG_track_prototype_users) { | |
| 1972 DCHECK(new_map->is_prototype_map()); | |
| 1973 DCHECK(object->map() == *new_map); | |
| 1974 new_map->set_prototype_info(old_map->prototype_info()); | |
| 1975 old_map->set_prototype_info(Smi::FromInt(0)); | |
| 1976 if (FLAG_trace_prototype_users) { | |
| 1977 PrintF("Moving prototype_info %p from map %p to map %p.\n", | |
| 1978 reinterpret_cast<void*>(new_map->prototype_info()), | |
| 1979 reinterpret_cast<void*>(*old_map), | |
| 1980 reinterpret_cast<void*>(*new_map)); | |
| 1981 } | |
| 1982 } | |
| 1983 } | 1988 } |
| 1984 | 1989 |
| 1985 | 1990 |
| 1986 // To migrate a fast instance to a fast map: | 1991 // To migrate a fast instance to a fast map: |
| 1987 // - First check whether the instance needs to be rewritten. If not, simply | 1992 // - First check whether the instance needs to be rewritten. If not, simply |
| 1988 // change the map. | 1993 // change the map. |
| 1989 // - Otherwise, allocate a fixed array large enough to hold all fields, in | 1994 // - Otherwise, allocate a fixed array large enough to hold all fields, in |
| 1990 // addition to unused space. | 1995 // addition to unused space. |
| 1991 // - Copy all existing properties in, in the following order: backing store | 1996 // - Copy all existing properties in, in the following order: backing store |
| 1992 // properties, unused fields, inobject properties. | 1997 // properties, unused fields, inobject properties. |
| (...skipping 2773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4766 } | 4771 } |
| 4767 | 4772 |
| 4768 Handle<Map> old_map(object->map(), isolate); | 4773 Handle<Map> old_map(object->map(), isolate); |
| 4769 | 4774 |
| 4770 int inobject_props = old_map->inobject_properties(); | 4775 int inobject_props = old_map->inobject_properties(); |
| 4771 | 4776 |
| 4772 // Allocate new map. | 4777 // Allocate new map. |
| 4773 Handle<Map> new_map = Map::CopyDropDescriptors(old_map); | 4778 Handle<Map> new_map = Map::CopyDropDescriptors(old_map); |
| 4774 new_map->set_dictionary_map(false); | 4779 new_map->set_dictionary_map(false); |
| 4775 | 4780 |
| 4776 if (old_map->is_prototype_map() && FLAG_track_prototype_users) { | 4781 UpdatePrototypeUserRegistration(old_map, new_map, isolate); |
| 4777 DCHECK(new_map->is_prototype_map()); | |
| 4778 | |
| 4779 Object* maybe_old_prototype = old_map->prototype(); | |
| 4780 if (maybe_old_prototype->IsJSObject()) { | |
| 4781 Handle<JSObject> old_prototype(JSObject::cast(maybe_old_prototype)); | |
| 4782 bool was_registered = | |
| 4783 JSObject::UnregisterPrototypeUser(old_prototype, old_map); | |
| 4784 if (was_registered) { | |
| 4785 JSObject::LazyRegisterPrototypeUser(new_map, isolate); | |
| 4786 } | |
| 4787 } | |
| 4788 new_map->set_prototype_info(old_map->prototype_info()); | |
| 4789 old_map->set_prototype_info(Smi::FromInt(0)); | |
| 4790 if (FLAG_trace_prototype_users) { | |
| 4791 PrintF("Moving prototype_info %p from map %p to map %p.\n", | |
| 4792 reinterpret_cast<void*>(new_map->prototype_info()), | |
| 4793 reinterpret_cast<void*>(*old_map), | |
| 4794 reinterpret_cast<void*>(*new_map)); | |
| 4795 } | |
| 4796 } | |
| 4797 | 4782 |
| 4798 #if TRACE_MAPS | 4783 #if TRACE_MAPS |
| 4799 if (FLAG_trace_maps) { | 4784 if (FLAG_trace_maps) { |
| 4800 PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n", | 4785 PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n", |
| 4801 reinterpret_cast<void*>(*old_map), reinterpret_cast<void*>(*new_map), | 4786 reinterpret_cast<void*>(*old_map), reinterpret_cast<void*>(*new_map), |
| 4802 reason); | 4787 reason); |
| 4803 } | 4788 } |
| 4804 #endif | 4789 #endif |
| 4805 | 4790 |
| 4806 if (instance_descriptor_length == 0) { | 4791 if (instance_descriptor_length == 0) { |
| (...skipping 3496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8303 : array->GetIsolate()->factory()->NewWeakCell(value); | 8288 : array->GetIsolate()->factory()->NewWeakCell(value); |
| 8304 Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell); | 8289 Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell); |
| 8305 if (FLAG_trace_weak_arrays) { | 8290 if (FLAG_trace_weak_arrays) { |
| 8306 PrintF("[WeakFixedArray: storing at index %d ]\n", index); | 8291 PrintF("[WeakFixedArray: storing at index %d ]\n", index); |
| 8307 } | 8292 } |
| 8308 array->set_last_used_index(index); | 8293 array->set_last_used_index(index); |
| 8309 } | 8294 } |
| 8310 | 8295 |
| 8311 | 8296 |
| 8312 // static | 8297 // static |
| 8313 Handle<WeakFixedArray> WeakFixedArray::Add( | 8298 Handle<WeakFixedArray> WeakFixedArray::Add(Handle<Object> maybe_array, |
| 8314 Handle<Object> maybe_array, Handle<HeapObject> value, | 8299 Handle<HeapObject> value, |
| 8315 SearchForDuplicates search_for_duplicates, bool* was_present) { | 8300 int* assigned_index) { |
| 8316 Handle<WeakFixedArray> array = | 8301 Handle<WeakFixedArray> array = |
| 8317 (maybe_array.is_null() || !maybe_array->IsWeakFixedArray()) | 8302 (maybe_array.is_null() || !maybe_array->IsWeakFixedArray()) |
| 8318 ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null()) | 8303 ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null()) |
| 8319 : Handle<WeakFixedArray>::cast(maybe_array); | 8304 : Handle<WeakFixedArray>::cast(maybe_array); |
| 8320 if (was_present != NULL) *was_present = false; | |
| 8321 if (search_for_duplicates == kAddIfNotFound) { | |
| 8322 for (int i = 0; i < array->Length(); ++i) { | |
| 8323 if (array->Get(i) == *value) { | |
| 8324 if (was_present != NULL) *was_present = true; | |
| 8325 return array; | |
| 8326 } | |
| 8327 } | |
| 8328 #if 0 // Enable this if you want to check your search_for_duplicates flags. | |
| 8329 } else { | |
| 8330 for (int i = 0; i < array->Length(); ++i) { | |
| 8331 DCHECK_NE(*value, array->Get(i)); | |
| 8332 } | |
| 8333 #endif | |
| 8334 } | |
| 8335 | |
| 8336 // Try to store the new entry if there's room. Optimize for consecutive | 8305 // Try to store the new entry if there's room. Optimize for consecutive |
| 8337 // accesses. | 8306 // accesses. |
| 8338 int first_index = array->last_used_index(); | 8307 int first_index = array->last_used_index(); |
| 8339 if (array->Length() > 0) { | 8308 int length = array->Length(); |
| 8309 if (length > 0) { |
| 8340 for (int i = first_index;;) { | 8310 for (int i = first_index;;) { |
| 8341 if (array->IsEmptySlot((i))) { | 8311 if (array->IsEmptySlot((i))) { |
| 8342 WeakFixedArray::Set(array, i, value); | 8312 WeakFixedArray::Set(array, i, value); |
| 8313 if (assigned_index != NULL) *assigned_index = i; |
| 8343 return array; | 8314 return array; |
| 8344 } | 8315 } |
| 8345 if (FLAG_trace_weak_arrays) { | 8316 if (FLAG_trace_weak_arrays) { |
| 8346 PrintF("[WeakFixedArray: searching for free slot]\n"); | 8317 PrintF("[WeakFixedArray: searching for free slot]\n"); |
| 8347 } | 8318 } |
| 8348 i = (i + 1) % array->Length(); | 8319 i = (i + 1) % length; |
| 8349 if (i == first_index) break; | 8320 if (i == first_index) break; |
| 8350 } | 8321 } |
| 8351 } | 8322 } |
| 8352 | 8323 |
| 8353 // No usable slot found, grow the array. | 8324 // No usable slot found, grow the array. |
| 8354 int new_length = | 8325 int new_length = length == 0 ? 1 : length + (length >> 1) + 4; |
| 8355 array->Length() == 0 ? 1 : array->Length() + (array->Length() >> 1) + 4; | |
| 8356 Handle<WeakFixedArray> new_array = | 8326 Handle<WeakFixedArray> new_array = |
| 8357 Allocate(array->GetIsolate(), new_length, array); | 8327 Allocate(array->GetIsolate(), new_length, array); |
| 8358 if (FLAG_trace_weak_arrays) { | 8328 if (FLAG_trace_weak_arrays) { |
| 8359 PrintF("[WeakFixedArray: growing to size %d ]\n", new_length); | 8329 PrintF("[WeakFixedArray: growing to size %d ]\n", new_length); |
| 8360 } | 8330 } |
| 8361 WeakFixedArray::Set(new_array, array->Length(), value); | 8331 WeakFixedArray::Set(new_array, length, value); |
| 8332 if (assigned_index != NULL) *assigned_index = length; |
| 8362 return new_array; | 8333 return new_array; |
| 8363 } | 8334 } |
| 8364 | 8335 |
| 8365 | 8336 |
| 8337 template <class CompactionCallback> |
| 8366 void WeakFixedArray::Compact() { | 8338 void WeakFixedArray::Compact() { |
| 8367 FixedArray* array = FixedArray::cast(this); | 8339 FixedArray* array = FixedArray::cast(this); |
| 8368 int new_length = kFirstIndex; | 8340 int new_length = kFirstIndex; |
| 8369 for (int i = kFirstIndex; i < array->length(); i++) { | 8341 for (int i = kFirstIndex; i < array->length(); i++) { |
| 8370 Object* element = array->get(i); | 8342 Object* element = array->get(i); |
| 8371 if (element->IsSmi()) continue; | 8343 if (element->IsSmi()) continue; |
| 8372 if (WeakCell::cast(element)->cleared()) continue; | 8344 if (WeakCell::cast(element)->cleared()) continue; |
| 8345 Object* value = WeakCell::cast(element)->value(); |
| 8346 CompactionCallback::Callback(value, i - kFirstIndex, |
| 8347 new_length - kFirstIndex); |
| 8373 array->set(new_length++, element); | 8348 array->set(new_length++, element); |
| 8374 } | 8349 } |
| 8375 array->Shrink(new_length); | 8350 array->Shrink(new_length); |
| 8376 set_last_used_index(0); | 8351 set_last_used_index(0); |
| 8377 } | 8352 } |
| 8378 | 8353 |
| 8379 | 8354 |
| 8355 void JSObject::PrototypeRegistryCompactionCallback::Callback(Object* value, |
| 8356 int old_index, |
| 8357 int new_index) { |
| 8358 DCHECK(value->IsMap() && Map::cast(value)->is_prototype_map()); |
| 8359 Map* map = Map::cast(value); |
| 8360 DCHECK(map->prototype_info()->IsPrototypeInfo()); |
| 8361 PrototypeInfo* proto_info = PrototypeInfo::cast(map->prototype_info()); |
| 8362 DCHECK_EQ(old_index, proto_info->registry_slot()); |
| 8363 proto_info->set_registry_slot(new_index); |
| 8364 } |
| 8365 |
| 8366 |
| 8367 template void WeakFixedArray::Compact<WeakFixedArray::NullCallback>(); |
| 8368 template void |
| 8369 WeakFixedArray::Compact<JSObject::PrototypeRegistryCompactionCallback>(); |
| 8370 |
| 8371 |
| 8380 bool WeakFixedArray::Remove(Handle<HeapObject> value) { | 8372 bool WeakFixedArray::Remove(Handle<HeapObject> value) { |
| 8381 if (Length() == 0) return false; | 8373 if (Length() == 0) return false; |
| 8382 // Optimize for the most recently added element to be removed again. | 8374 // Optimize for the most recently added element to be removed again. |
| 8383 int first_index = last_used_index(); | 8375 int first_index = last_used_index(); |
| 8384 for (int i = first_index;;) { | 8376 for (int i = first_index;;) { |
| 8385 if (Get(i) == *value) { | 8377 if (Get(i) == *value) { |
| 8386 Clear(i); | 8378 Clear(i); |
| 8387 // Users of WeakFixedArray should make sure that there are no duplicates, | 8379 // Users of WeakFixedArray should make sure that there are no duplicates. |
| 8388 // they can use Add(..., kAddIfNotFound) if necessary. | |
| 8389 return true; | 8380 return true; |
| 8390 } | 8381 } |
| 8391 i = (i + 1) % Length(); | 8382 i = (i + 1) % Length(); |
| 8392 if (i == first_index) return false; | 8383 if (i == first_index) return false; |
| 8393 } | 8384 } |
| 8394 UNREACHABLE(); | 8385 UNREACHABLE(); |
| 8395 } | 8386 } |
| 8396 | 8387 |
| 8397 | 8388 |
| 8398 // static | 8389 // static |
| (...skipping 1730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10129 | 10120 |
| 10130 | 10121 |
| 10131 // static | 10122 // static |
| 10132 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) { | 10123 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) { |
| 10133 DCHECK(FLAG_track_prototype_users); | 10124 DCHECK(FLAG_track_prototype_users); |
| 10134 // Contract: In line with InvalidatePrototypeChains()'s requirements, | 10125 // Contract: In line with InvalidatePrototypeChains()'s requirements, |
| 10135 // leaf maps don't need to register as users, only prototypes do. | 10126 // leaf maps don't need to register as users, only prototypes do. |
| 10136 DCHECK(user->is_prototype_map()); | 10127 DCHECK(user->is_prototype_map()); |
| 10137 | 10128 |
| 10138 Handle<Map> current_user = user; | 10129 Handle<Map> current_user = user; |
| 10130 Handle<PrototypeInfo> current_user_info = |
| 10131 Map::GetOrCreatePrototypeInfo(user, isolate); |
| 10139 for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) { | 10132 for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) { |
| 10133 // Walk up the prototype chain as far as links haven't been registered yet. |
| 10134 if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) { |
| 10135 break; |
| 10136 } |
| 10140 Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter); | 10137 Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter); |
| 10141 if (maybe_proto->IsJSGlobalProxy()) continue; | 10138 if (maybe_proto->IsJSGlobalProxy()) continue; |
| 10142 // Proxies on the prototype chain are not supported. | 10139 // Proxies on the prototype chain are not supported. |
| 10143 if (maybe_proto->IsJSProxy()) return; | 10140 if (maybe_proto->IsJSProxy()) return; |
| 10144 Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto); | 10141 Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto); |
| 10145 bool just_registered = | 10142 Handle<PrototypeInfo> proto_info = |
| 10146 RegisterPrototypeUserIfNotRegistered(proto, current_user, isolate); | 10143 Map::GetOrCreatePrototypeInfo(proto, isolate); |
| 10147 // Walk up the prototype chain as far as links haven't been registered yet. | 10144 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate); |
| 10148 if (!just_registered) break; | 10145 int slot = 0; |
| 10146 Handle<WeakFixedArray> new_array = |
| 10147 WeakFixedArray::Add(maybe_registry, current_user, &slot); |
| 10148 current_user_info->set_registry_slot(slot); |
| 10149 if (!maybe_registry.is_identical_to(new_array)) { |
| 10150 proto_info->set_prototype_users(*new_array); |
| 10151 } |
| 10152 if (FLAG_trace_prototype_users) { |
| 10153 PrintF("Registering %p as a user of prototype %p (map=%p).\n", |
| 10154 reinterpret_cast<void*>(*current_user), |
| 10155 reinterpret_cast<void*>(*proto), |
| 10156 reinterpret_cast<void*>(proto->map())); |
| 10157 } |
| 10158 |
| 10149 current_user = handle(proto->map(), isolate); | 10159 current_user = handle(proto->map(), isolate); |
| 10160 current_user_info = proto_info; |
| 10150 } | 10161 } |
| 10151 } | 10162 } |
| 10152 | 10163 |
| 10153 | 10164 |
| 10154 // Returns true if the user was not yet registered. | |
| 10155 // static | |
| 10156 bool JSObject::RegisterPrototypeUserIfNotRegistered(Handle<JSObject> prototype, | |
| 10157 Handle<HeapObject> user, | |
| 10158 Isolate* isolate) { | |
| 10159 Handle<PrototypeInfo> proto_info = | |
| 10160 Map::GetOrCreatePrototypeInfo(prototype, isolate); | |
| 10161 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate); | |
| 10162 bool was_present = false; | |
| 10163 Handle<WeakFixedArray> new_array = WeakFixedArray::Add( | |
| 10164 maybe_registry, user, WeakFixedArray::kAddIfNotFound, &was_present); | |
| 10165 if (!maybe_registry.is_identical_to(new_array)) { | |
| 10166 proto_info->set_prototype_users(*new_array); | |
| 10167 } | |
| 10168 if (FLAG_trace_prototype_users && !was_present) { | |
| 10169 PrintF("Registering %p as a user of prototype %p (map=%p).\n", | |
| 10170 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype), | |
| 10171 reinterpret_cast<void*>(prototype->map())); | |
| 10172 } | |
| 10173 return !was_present; | |
| 10174 } | |
| 10175 | |
| 10176 | |
| 10177 // Can be called regardless of whether |user| was actually registered with | 10165 // Can be called regardless of whether |user| was actually registered with |
| 10178 // |prototype|. Returns true when there was a registration. | 10166 // |prototype|. Returns true when there was a registration. |
| 10179 // static | 10167 // static |
| 10180 bool JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype, | 10168 bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) { |
| 10181 Handle<HeapObject> user) { | 10169 DCHECK(user->is_prototype_map()); |
| 10182 Isolate* isolate = prototype->GetIsolate(); | 10170 // If it doesn't have a PrototypeInfo, it was never registered. |
| 10171 if (!user->prototype_info()->IsPrototypeInfo()) return false; |
| 10172 // If it doesn't have a prototype, it can't be registered. |
| 10173 if (!user->prototype()->IsJSObject()) return false; |
| 10174 Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate); |
| 10175 Handle<PrototypeInfo> user_info = |
| 10176 Map::GetOrCreatePrototypeInfo(user, isolate); |
| 10177 int slot = user_info->registry_slot(); |
| 10178 if (slot == PrototypeInfo::UNREGISTERED) return false; |
| 10183 if (prototype->IsJSGlobalProxy()) { | 10179 if (prototype->IsJSGlobalProxy()) { |
| 10184 PrototypeIterator iter(isolate, prototype); | 10180 PrototypeIterator iter(isolate, prototype); |
| 10185 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 10181 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| 10186 } | 10182 } |
| 10187 DCHECK(prototype->map()->is_prototype_map()); | 10183 DCHECK(prototype->map()->is_prototype_map()); |
| 10188 Object* maybe_proto_info = prototype->map()->prototype_info(); | 10184 Object* maybe_proto_info = prototype->map()->prototype_info(); |
| 10189 if (!maybe_proto_info->IsPrototypeInfo()) return false; | 10185 // User knows its registry slot, prototype info and user registry must exist. |
| 10186 DCHECK(maybe_proto_info->IsPrototypeInfo()); |
| 10190 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info), | 10187 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info), |
| 10191 isolate); | 10188 isolate); |
| 10192 Object* maybe_registry = proto_info->prototype_users(); | 10189 Object* maybe_registry = proto_info->prototype_users(); |
| 10193 if (!maybe_registry->IsWeakFixedArray()) return false; | 10190 DCHECK(maybe_registry->IsWeakFixedArray()); |
| 10194 bool result = WeakFixedArray::cast(maybe_registry)->Remove(user); | 10191 DCHECK(WeakFixedArray::cast(maybe_registry)->Get(slot) == *user); |
| 10195 if (FLAG_trace_prototype_users && result) { | 10192 WeakFixedArray::cast(maybe_registry)->Clear(slot); |
| 10193 if (FLAG_trace_prototype_users) { |
| 10196 PrintF("Unregistering %p as a user of prototype %p.\n", | 10194 PrintF("Unregistering %p as a user of prototype %p.\n", |
| 10197 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype)); | 10195 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype)); |
| 10198 } | 10196 } |
| 10199 return result; | 10197 return true; |
| 10200 } | 10198 } |
| 10201 | 10199 |
| 10202 | 10200 |
| 10203 static void InvalidatePrototypeChainsInternal(Map* map) { | 10201 static void InvalidatePrototypeChainsInternal(Map* map) { |
| 10204 if (!map->is_prototype_map()) return; | 10202 if (!map->is_prototype_map()) return; |
| 10205 if (FLAG_trace_prototype_users) { | 10203 if (FLAG_trace_prototype_users) { |
| 10206 PrintF("Invalidating prototype map %p 's cell\n", | 10204 PrintF("Invalidating prototype map %p 's cell\n", |
| 10207 reinterpret_cast<void*>(map)); | 10205 reinterpret_cast<void*>(map)); |
| 10208 } | 10206 } |
| 10209 Object* maybe_proto_info = map->prototype_info(); | 10207 Object* maybe_proto_info = map->prototype_info(); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10251 if (maybe_proto_info->IsPrototypeInfo()) { | 10249 if (maybe_proto_info->IsPrototypeInfo()) { |
| 10252 return handle(PrototypeInfo::cast(maybe_proto_info), isolate); | 10250 return handle(PrototypeInfo::cast(maybe_proto_info), isolate); |
| 10253 } | 10251 } |
| 10254 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo(); | 10252 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo(); |
| 10255 prototype->map()->set_prototype_info(*proto_info); | 10253 prototype->map()->set_prototype_info(*proto_info); |
| 10256 return proto_info; | 10254 return proto_info; |
| 10257 } | 10255 } |
| 10258 | 10256 |
| 10259 | 10257 |
| 10260 // static | 10258 // static |
| 10259 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<Map> prototype_map, |
| 10260 Isolate* isolate) { |
| 10261 Object* maybe_proto_info = prototype_map->prototype_info(); |
| 10262 if (maybe_proto_info->IsPrototypeInfo()) { |
| 10263 return handle(PrototypeInfo::cast(maybe_proto_info), isolate); |
| 10264 } |
| 10265 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo(); |
| 10266 prototype_map->set_prototype_info(*proto_info); |
| 10267 return proto_info; |
| 10268 } |
| 10269 |
| 10270 |
| 10271 // static |
| 10261 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, | 10272 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, |
| 10262 Isolate* isolate) { | 10273 Isolate* isolate) { |
| 10263 Handle<Object> maybe_prototype(map->prototype(), isolate); | 10274 Handle<Object> maybe_prototype(map->prototype(), isolate); |
| 10264 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null(); | 10275 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null(); |
| 10265 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype); | 10276 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype); |
| 10266 if (prototype->IsJSGlobalProxy()) { | 10277 if (prototype->IsJSGlobalProxy()) { |
| 10267 PrototypeIterator iter(isolate, prototype); | 10278 PrototypeIterator iter(isolate, prototype); |
| 10268 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 10279 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| 10269 } | 10280 } |
| 10270 // Ensure the prototype is registered with its own prototypes so its cell | 10281 // Ensure the prototype is registered with its own prototypes so its cell |
| (...skipping 7008 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17279 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell, | 17290 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell, |
| 17280 Handle<Object> new_value) { | 17291 Handle<Object> new_value) { |
| 17281 if (cell->value() != *new_value) { | 17292 if (cell->value() != *new_value) { |
| 17282 cell->set_value(*new_value); | 17293 cell->set_value(*new_value); |
| 17283 Isolate* isolate = cell->GetIsolate(); | 17294 Isolate* isolate = cell->GetIsolate(); |
| 17284 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17295 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 17285 isolate, DependentCode::kPropertyCellChangedGroup); | 17296 isolate, DependentCode::kPropertyCellChangedGroup); |
| 17286 } | 17297 } |
| 17287 } | 17298 } |
| 17288 } } // namespace v8::internal | 17299 } } // namespace v8::internal |
| OLD | NEW |