| 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 |