Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: src/objects.cc

Issue 1110513002: Reland "Lazily register prototype users..." (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: assert trumps comment Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects.h ('k') | test/cctest/test-heap.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
1904 } 1904 }
1905 1905
1906 1906
1907 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, 1907 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
1908 int expected_additional_properties) { 1908 int expected_additional_properties) {
1909 if (object->map() == *new_map) return; 1909 if (object->map() == *new_map) return;
1910 // If this object is a prototype (the callee will check), invalidate any 1910 // If this object is a prototype (the callee will check), invalidate any
1911 // prototype chains involving it. 1911 // prototype chains involving it.
1912 InvalidatePrototypeChains(object->map()); 1912 InvalidatePrototypeChains(object->map());
1913 Handle<Map> old_map(object->map()); 1913 Handle<Map> old_map(object->map());
1914
1915 // If the map was registered with its prototype before, ensure that it
1916 // registers with its new prototype now. This preserves the invariant that
1917 // when a map on a prototype chain is registered with its prototype, then
1918 // all prototypes further up the chain are also registered with their
1919 // respective prototypes.
1920 Object* maybe_old_prototype = old_map->prototype();
1921 if (maybe_old_prototype->IsJSObject()) {
1922 Handle<JSObject> old_prototype(JSObject::cast(maybe_old_prototype));
1923 bool was_registered =
1924 JSObject::UnregisterPrototypeUser(old_prototype, old_map);
1925 if (was_registered) {
1926 JSObject::LazyRegisterPrototypeUser(new_map, new_map->GetIsolate());
1927 }
1928 }
1929
1914 if (object->HasFastProperties()) { 1930 if (object->HasFastProperties()) {
1915 if (!new_map->is_dictionary_map()) { 1931 if (!new_map->is_dictionary_map()) {
1916 MigrateFastToFast(object, new_map); 1932 MigrateFastToFast(object, new_map);
1917 if (old_map->is_prototype_map()) { 1933 if (old_map->is_prototype_map()) {
1918 // Clear out the old descriptor array to avoid problems to sharing 1934 // Clear out the old descriptor array to avoid problems to sharing
1919 // the descriptor array without using an explicit. 1935 // the descriptor array without using an explicit.
1920 old_map->InitializeDescriptors( 1936 old_map->InitializeDescriptors(
1921 old_map->GetHeap()->empty_descriptor_array(), 1937 old_map->GetHeap()->empty_descriptor_array(),
1922 LayoutDescriptor::FastPointerLayout()); 1938 LayoutDescriptor::FastPointerLayout());
1923 // Ensure that no transition was inserted for prototype migrations. 1939 // Ensure that no transition was inserted for prototype migrations.
1924 DCHECK_EQ(0, TransitionArray::NumberOfTransitions( 1940 DCHECK_EQ(0, TransitionArray::NumberOfTransitions(
1925 old_map->raw_transitions())); 1941 old_map->raw_transitions()));
1926 DCHECK(new_map->GetBackPointer()->IsUndefined()); 1942 DCHECK(new_map->GetBackPointer()->IsUndefined());
1927 } 1943 }
1928 } else { 1944 } else {
1929 MigrateFastToSlow(object, new_map, expected_additional_properties); 1945 MigrateFastToSlow(object, new_map, expected_additional_properties);
1930 } 1946 }
1931 } else { 1947 } else {
1932 // For slow-to-fast migrations JSObject::MigrateSlowToFast() 1948 // For slow-to-fast migrations JSObject::MigrateSlowToFast()
1933 // must be used instead. 1949 // must be used instead.
1934 CHECK(new_map->is_dictionary_map()); 1950 CHECK(new_map->is_dictionary_map());
1935 1951
1936 // Slow-to-slow migration is trivial. 1952 // Slow-to-slow migration is trivial.
1937 object->set_map(*new_map); 1953 object->set_map(*new_map);
1938 } 1954 }
1939 if (old_map->is_prototype_map()) { 1955
1956 // Careful: Don't allocate here!
1957 // For some callers of this method, |object| might be in an inconsistent
1958 // state now: the new map might have a new elements_kind, but the object's
1959 // elements pointer hasn't been updated yet. Callers will fix this, but in
1960 // the meantime, (indirectly) calling JSObjectVerify() must be avoided.
1961 DisallowHeapAllocation no_object_verification;
1962
1963 if (old_map->is_prototype_map() && FLAG_track_prototype_users) {
1940 DCHECK(new_map->is_prototype_map()); 1964 DCHECK(new_map->is_prototype_map());
1941 DCHECK(object->map() == *new_map); 1965 DCHECK(object->map() == *new_map);
1942 new_map->set_prototype_info(old_map->prototype_info()); 1966 new_map->set_prototype_info(old_map->prototype_info());
1943 old_map->set_prototype_info(Smi::FromInt(0)); 1967 old_map->set_prototype_info(Smi::FromInt(0));
1944 if (FLAG_trace_prototype_users) { 1968 if (FLAG_trace_prototype_users) {
1945 PrintF("Moving prototype_info %p from map %p to map %p.\n", 1969 PrintF("Moving prototype_info %p from map %p to map %p.\n",
1946 reinterpret_cast<void*>(new_map->prototype_info()), 1970 reinterpret_cast<void*>(new_map->prototype_info()),
1947 reinterpret_cast<void*>(*old_map), 1971 reinterpret_cast<void*>(*old_map),
1948 reinterpret_cast<void*>(*new_map)); 1972 reinterpret_cast<void*>(*new_map));
1949 } 1973 }
(...skipping 5131 matching lines...) Expand 10 before | Expand all | Expand 10 after
7081 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, 7105 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
7082 Handle<Name> name, SimpleTransitionFlag flag) { 7106 Handle<Name> name, SimpleTransitionFlag flag) {
7083 parent->set_owns_descriptors(false); 7107 parent->set_owns_descriptors(false);
7084 if (parent->is_prototype_map()) { 7108 if (parent->is_prototype_map()) {
7085 DCHECK(child->is_prototype_map()); 7109 DCHECK(child->is_prototype_map());
7086 #if TRACE_MAPS 7110 #if TRACE_MAPS
7087 Map::TraceTransition("NoTransition", *parent, *child, *name); 7111 Map::TraceTransition("NoTransition", *parent, *child, *name);
7088 #endif 7112 #endif
7089 } else { 7113 } else {
7090 TransitionArray::Insert(parent, name, child, flag); 7114 TransitionArray::Insert(parent, name, child, flag);
7091 if (child->prototype()->IsJSObject()) {
7092 Handle<JSObject> proto(JSObject::cast(child->prototype()));
7093 if (!ShouldRegisterAsPrototypeUser(child, proto)) {
7094 JSObject::UnregisterPrototypeUser(proto, child);
7095 }
7096 }
7097 #if TRACE_MAPS 7115 #if TRACE_MAPS
7098 Map::TraceTransition("Transition", *parent, *child, *name); 7116 Map::TraceTransition("Transition", *parent, *child, *name);
7099 #endif 7117 #endif
7100 } 7118 }
7101 } 7119 }
7102 7120
7103 7121
7104 Handle<Map> Map::CopyReplaceDescriptors( 7122 Handle<Map> Map::CopyReplaceDescriptors(
7105 Handle<Map> map, Handle<DescriptorArray> descriptors, 7123 Handle<Map> map, Handle<DescriptorArray> descriptors,
7106 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag, 7124 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
(...skipping 1144 matching lines...) Expand 10 before | Expand all | Expand 10 after
8251 if (FLAG_trace_weak_arrays) { 8269 if (FLAG_trace_weak_arrays) {
8252 PrintF("[WeakFixedArray: storing at index %d ]\n", index); 8270 PrintF("[WeakFixedArray: storing at index %d ]\n", index);
8253 } 8271 }
8254 array->set_last_used_index(index); 8272 array->set_last_used_index(index);
8255 } 8273 }
8256 8274
8257 8275
8258 // static 8276 // static
8259 Handle<WeakFixedArray> WeakFixedArray::Add( 8277 Handle<WeakFixedArray> WeakFixedArray::Add(
8260 Handle<Object> maybe_array, Handle<HeapObject> value, 8278 Handle<Object> maybe_array, Handle<HeapObject> value,
8261 SearchForDuplicates search_for_duplicates) { 8279 SearchForDuplicates search_for_duplicates, bool* was_present) {
8262 Handle<WeakFixedArray> array = 8280 Handle<WeakFixedArray> array =
8263 (maybe_array.is_null() || !maybe_array->IsWeakFixedArray()) 8281 (maybe_array.is_null() || !maybe_array->IsWeakFixedArray())
8264 ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null()) 8282 ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null())
8265 : Handle<WeakFixedArray>::cast(maybe_array); 8283 : Handle<WeakFixedArray>::cast(maybe_array);
8266 8284 if (was_present != NULL) *was_present = false;
8267 if (search_for_duplicates == kAddIfNotFound) { 8285 if (search_for_duplicates == kAddIfNotFound) {
8268 for (int i = 0; i < array->Length(); ++i) { 8286 for (int i = 0; i < array->Length(); ++i) {
8269 if (array->Get(i) == *value) return array; 8287 if (array->Get(i) == *value) {
8288 if (was_present != NULL) *was_present = true;
8289 return array;
8290 }
8270 } 8291 }
8271 #if 0 // Enable this if you want to check your search_for_duplicates flags. 8292 #if 0 // Enable this if you want to check your search_for_duplicates flags.
8272 } else { 8293 } else {
8273 for (int i = 0; i < array->Length(); ++i) { 8294 for (int i = 0; i < array->Length(); ++i) {
8274 DCHECK_NE(*value, array->Get(i)); 8295 DCHECK_NE(*value, array->Get(i));
8275 } 8296 }
8276 #endif 8297 #endif
8277 } 8298 }
8278 8299
8279 // Try to store the new entry if there's room. Optimize for consecutive 8300 // Try to store the new entry if there's room. Optimize for consecutive
8280 // accesses. 8301 // accesses.
8281 int first_index = array->last_used_index(); 8302 int first_index = array->last_used_index();
8282 for (int i = first_index;;) { 8303 if (array->Length() > 0) {
8283 if (array->IsEmptySlot((i))) { 8304 for (int i = first_index;;) {
8284 WeakFixedArray::Set(array, i, value); 8305 if (array->IsEmptySlot((i))) {
8285 return array; 8306 WeakFixedArray::Set(array, i, value);
8307 return array;
8308 }
8309 if (FLAG_trace_weak_arrays) {
8310 PrintF("[WeakFixedArray: searching for free slot]\n");
8311 }
8312 i = (i + 1) % array->Length();
8313 if (i == first_index) break;
8286 } 8314 }
8287 if (FLAG_trace_weak_arrays) {
8288 PrintF("[WeakFixedArray: searching for free slot]\n");
8289 }
8290 i = (i + 1) % array->Length();
8291 if (i == first_index) break;
8292 } 8315 }
8293 8316
8294 // No usable slot found, grow the array. 8317 // No usable slot found, grow the array.
8295 int new_length = array->Length() + (array->Length() >> 1) + 4; 8318 int new_length =
8319 array->Length() == 0 ? 1 : array->Length() + (array->Length() >> 1) + 4;
8296 Handle<WeakFixedArray> new_array = 8320 Handle<WeakFixedArray> new_array =
8297 Allocate(array->GetIsolate(), new_length, array); 8321 Allocate(array->GetIsolate(), new_length, array);
8298 if (FLAG_trace_weak_arrays) { 8322 if (FLAG_trace_weak_arrays) {
8299 PrintF("[WeakFixedArray: growing to size %d ]\n", new_length); 8323 PrintF("[WeakFixedArray: growing to size %d ]\n", new_length);
8300 } 8324 }
8301 WeakFixedArray::Set(new_array, array->Length(), value); 8325 WeakFixedArray::Set(new_array, array->Length(), value);
8302 return new_array; 8326 return new_array;
8303 } 8327 }
8304 8328
8305 8329
8306 void WeakFixedArray::Compact() { 8330 void WeakFixedArray::Compact() {
8307 FixedArray* array = FixedArray::cast(this); 8331 FixedArray* array = FixedArray::cast(this);
8308 int new_length = kFirstIndex; 8332 int new_length = kFirstIndex;
8309 for (int i = kFirstIndex; i < array->length(); i++) { 8333 for (int i = kFirstIndex; i < array->length(); i++) {
8310 Object* element = array->get(i); 8334 Object* element = array->get(i);
8311 if (element->IsSmi()) continue; 8335 if (element->IsSmi()) continue;
8312 if (WeakCell::cast(element)->cleared()) continue; 8336 if (WeakCell::cast(element)->cleared()) continue;
8313 array->set(new_length++, element); 8337 array->set(new_length++, element);
8314 } 8338 }
8315 array->Shrink(new_length); 8339 array->Shrink(new_length);
8316 set_last_used_index(0); 8340 set_last_used_index(0);
8317 } 8341 }
8318 8342
8319 8343
8320 void WeakFixedArray::Remove(Handle<HeapObject> value) { 8344 bool WeakFixedArray::Remove(Handle<HeapObject> value) {
8345 if (Length() == 0) return false;
8321 // Optimize for the most recently added element to be removed again. 8346 // Optimize for the most recently added element to be removed again.
8322 int first_index = last_used_index(); 8347 int first_index = last_used_index();
8323 for (int i = first_index;;) { 8348 for (int i = first_index;;) {
8324 if (Get(i) == *value) { 8349 if (Get(i) == *value) {
8325 clear(i); 8350 clear(i);
8326 // Users of WeakFixedArray should make sure that there are no duplicates, 8351 // Users of WeakFixedArray should make sure that there are no duplicates,
8327 // they can use Add(..., kAddIfNotFound) if necessary. 8352 // they can use Add(..., kAddIfNotFound) if necessary.
8328 return; 8353 return true;
8329 } 8354 }
8330 i = (i + 1) % Length(); 8355 i = (i + 1) % Length();
8331 if (i == first_index) break; 8356 if (i == first_index) return false;
8332 } 8357 }
8358 UNREACHABLE();
8333 } 8359 }
8334 8360
8335 8361
8336 // static 8362 // static
8337 Handle<WeakFixedArray> WeakFixedArray::Allocate( 8363 Handle<WeakFixedArray> WeakFixedArray::Allocate(
8338 Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) { 8364 Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) {
8339 DCHECK(0 <= size); 8365 DCHECK(0 <= size);
8340 Handle<FixedArray> result = 8366 Handle<FixedArray> result =
8341 isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex); 8367 isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex);
8342 Handle<WeakFixedArray> casted_result = Handle<WeakFixedArray>::cast(result); 8368 Handle<WeakFixedArray> casted_result = Handle<WeakFixedArray>::cast(result);
(...skipping 1712 matching lines...) Expand 10 before | Expand all | Expand 10 after
10055 10081
10056 10082
10057 // static 10083 // static
10058 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) { 10084 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
10059 if (!object->map()->is_prototype_map()) return; 10085 if (!object->map()->is_prototype_map()) return;
10060 OptimizeAsPrototype(object, FAST_PROTOTYPE); 10086 OptimizeAsPrototype(object, FAST_PROTOTYPE);
10061 } 10087 }
10062 10088
10063 10089
10064 // static 10090 // static
10065 void JSObject::RegisterPrototypeUser(Handle<JSObject> prototype, 10091 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
10066 Handle<HeapObject> user) {
10067 DCHECK(FLAG_track_prototype_users); 10092 DCHECK(FLAG_track_prototype_users);
10068 Isolate* isolate = prototype->GetIsolate(); 10093 // Contract: In line with InvalidatePrototypeChains()'s requirements,
10069 if (prototype->IsJSGlobalProxy()) { 10094 // leaf maps don't need to register as users, only prototypes do.
10070 PrototypeIterator iter(isolate, prototype); 10095 DCHECK(user->is_prototype_map());
10071 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); 10096
10072 } 10097 Handle<Map> current_user = user;
10073 Handle<PrototypeInfo> proto_info; 10098 for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) {
10074 Object* maybe_proto_info = prototype->map()->prototype_info(); 10099 Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter);
10075 if (maybe_proto_info->IsPrototypeInfo()) { 10100 if (maybe_proto->IsJSGlobalProxy()) continue;
10076 proto_info = handle(PrototypeInfo::cast(maybe_proto_info), isolate); 10101 // Proxies on the prototype chain are not supported.
10077 } else { 10102 if (maybe_proto->IsJSProxy()) return;
10078 proto_info = isolate->factory()->NewPrototypeInfo(); 10103 Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto);
10079 prototype->map()->set_prototype_info(*proto_info); 10104 bool just_registered =
10080 } 10105 RegisterPrototypeUserIfNotRegistered(proto, current_user, isolate);
10081 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate); 10106 // Walk up the prototype chain as far as links haven't been registered yet.
10082 Handle<WeakFixedArray> new_array = WeakFixedArray::Add(maybe_registry, user); 10107 if (!just_registered) break;
10083 if (!maybe_registry.is_identical_to(new_array)) { 10108 current_user = handle(proto->map(), isolate);
10084 proto_info->set_prototype_users(*new_array);
10085 }
10086 if (FLAG_trace_prototype_users) {
10087 PrintF("Registering %p as a user of prototype %p.\n",
10088 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype));
10089 } 10109 }
10090 } 10110 }
10091 10111
10092 10112
10113 // Returns true if the user was not yet registered.
10093 // static 10114 // static
10094 void JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype, 10115 bool JSObject::RegisterPrototypeUserIfNotRegistered(Handle<JSObject> prototype,
10116 Handle<HeapObject> user,
10117 Isolate* isolate) {
10118 Handle<PrototypeInfo> proto_info =
10119 Map::GetOrCreatePrototypeInfo(prototype, isolate);
10120 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
10121 bool was_present = false;
10122 Handle<WeakFixedArray> new_array = WeakFixedArray::Add(
10123 maybe_registry, user, WeakFixedArray::kAddIfNotFound, &was_present);
10124 if (!maybe_registry.is_identical_to(new_array)) {
10125 proto_info->set_prototype_users(*new_array);
10126 }
10127 if (FLAG_trace_prototype_users && !was_present) {
10128 PrintF("Registering %p as a user of prototype %p (map=%p).\n",
10129 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype),
10130 reinterpret_cast<void*>(prototype->map()));
10131 }
10132 return !was_present;
10133 }
10134
10135
10136 // Can be called regardless of whether |user| was actually registered with
10137 // |prototype|. Returns true when there was a registration.
10138 // static
10139 bool JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype,
10095 Handle<HeapObject> user) { 10140 Handle<HeapObject> user) {
10096 Isolate* isolate = prototype->GetIsolate(); 10141 Isolate* isolate = prototype->GetIsolate();
10097 if (prototype->IsJSGlobalProxy()) { 10142 if (prototype->IsJSGlobalProxy()) {
10098 PrototypeIterator iter(isolate, prototype); 10143 PrototypeIterator iter(isolate, prototype);
10099 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); 10144 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
10100 } 10145 }
10101 DCHECK(prototype->map()->is_prototype_map()); 10146 DCHECK(prototype->map()->is_prototype_map());
10102 Object* maybe_proto_info = prototype->map()->prototype_info(); 10147 Object* maybe_proto_info = prototype->map()->prototype_info();
10103 if (!maybe_proto_info->IsPrototypeInfo()) return; 10148 if (!maybe_proto_info->IsPrototypeInfo()) return false;
10104 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info), 10149 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
10105 isolate); 10150 isolate);
10106 Object* maybe_registry = proto_info->prototype_users(); 10151 Object* maybe_registry = proto_info->prototype_users();
10107 if (!maybe_registry->IsWeakFixedArray()) return; 10152 if (!maybe_registry->IsWeakFixedArray()) return false;
10108 WeakFixedArray::cast(maybe_registry)->Remove(user); 10153 bool result = WeakFixedArray::cast(maybe_registry)->Remove(user);
10109 if (FLAG_trace_prototype_users) { 10154 if (FLAG_trace_prototype_users && result) {
10110 PrintF("Unregistering %p as a user of prototype %p.\n", 10155 PrintF("Unregistering %p as a user of prototype %p.\n",
10111 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype)); 10156 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype));
10112 } 10157 }
10158 return result;
10113 } 10159 }
10114 10160
10115 10161
10116 static void InvalidatePrototypeChainsInternal(Map* map) { 10162 static void InvalidatePrototypeChainsInternal(Map* map) {
10117 if (!map->is_prototype_map()) return; 10163 if (!map->is_prototype_map()) return;
10164 if (FLAG_trace_prototype_users) {
10165 PrintF("Invalidating prototype map %p 's cell\n",
10166 reinterpret_cast<void*>(map));
10167 }
10118 Object* maybe_proto_info = map->prototype_info(); 10168 Object* maybe_proto_info = map->prototype_info();
10119 if (!maybe_proto_info->IsPrototypeInfo()) return; 10169 if (!maybe_proto_info->IsPrototypeInfo()) return;
10120 PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info); 10170 PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info);
10121 Object* maybe_cell = proto_info->validity_cell(); 10171 Object* maybe_cell = proto_info->validity_cell();
10122 if (maybe_cell->IsCell()) { 10172 if (maybe_cell->IsCell()) {
10123 // Just set the value; the cell will be replaced lazily. 10173 // Just set the value; the cell will be replaced lazily.
10124 Cell* cell = Cell::cast(maybe_cell); 10174 Cell* cell = Cell::cast(maybe_cell);
10125 cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid)); 10175 cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
10126 } 10176 }
10127 10177
(...skipping 19 matching lines...) Expand all
10147 DisallowHeapAllocation no_gc; 10197 DisallowHeapAllocation no_gc;
10148 if (map->IsJSGlobalProxyMap()) { 10198 if (map->IsJSGlobalProxyMap()) {
10149 PrototypeIterator iter(map); 10199 PrototypeIterator iter(map);
10150 map = JSObject::cast(iter.GetCurrent())->map(); 10200 map = JSObject::cast(iter.GetCurrent())->map();
10151 } 10201 }
10152 InvalidatePrototypeChainsInternal(map); 10202 InvalidatePrototypeChainsInternal(map);
10153 } 10203 }
10154 10204
10155 10205
10156 // static 10206 // static
10207 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
10208 Isolate* isolate) {
10209 Object* maybe_proto_info = prototype->map()->prototype_info();
10210 if (maybe_proto_info->IsPrototypeInfo()) {
10211 return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
10212 }
10213 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
10214 prototype->map()->set_prototype_info(*proto_info);
10215 return proto_info;
10216 }
10217
10218
10219 // static
10157 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, 10220 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
10158 Isolate* isolate) { 10221 Isolate* isolate) {
10159 Handle<Object> maybe_prototype(map->prototype(), isolate); 10222 Handle<Object> maybe_prototype(map->prototype(), isolate);
10160 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null(); 10223 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null();
10161 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype); 10224 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
10162 if (prototype->IsJSGlobalProxy()) { 10225 if (prototype->IsJSGlobalProxy()) {
10163 PrototypeIterator iter(isolate, prototype); 10226 PrototypeIterator iter(isolate, prototype);
10164 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); 10227 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
10165 } 10228 }
10166 Handle<PrototypeInfo> proto_info( 10229 // Ensure the prototype is registered with its own prototypes so its cell
10167 PrototypeInfo::cast(prototype->map()->prototype_info()), isolate); 10230 // will be invalidated when necessary.
10231 JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
10232 isolate);
10233 Handle<PrototypeInfo> proto_info =
10234 GetOrCreatePrototypeInfo(prototype, isolate);
10168 Object* maybe_cell = proto_info->validity_cell(); 10235 Object* maybe_cell = proto_info->validity_cell();
10169 // Return existing cell if it's still valid. 10236 // Return existing cell if it's still valid.
10170 if (maybe_cell->IsCell()) { 10237 if (maybe_cell->IsCell()) {
10171 Handle<Cell> cell(Cell::cast(maybe_cell), isolate); 10238 Handle<Cell> cell(Cell::cast(maybe_cell), isolate);
10172 if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) { 10239 if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) {
10173 return handle(Cell::cast(maybe_cell), isolate); 10240 return cell;
10174 } 10241 }
10175 } 10242 }
10176 // Otherwise create a new cell. 10243 // Otherwise create a new cell.
10177 Handle<Cell> cell = isolate->factory()->NewCell( 10244 Handle<Cell> cell = isolate->factory()->NewCell(
10178 handle(Smi::FromInt(Map::kPrototypeChainValid), isolate)); 10245 handle(Smi::FromInt(Map::kPrototypeChainValid), isolate));
10179 proto_info->set_validity_cell(*cell); 10246 proto_info->set_validity_cell(*cell);
10180 return cell; 10247 return cell;
10181 } 10248 }
10182 10249
10183 10250
10251 // static
10184 void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype, 10252 void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype,
10185 PrototypeOptimizationMode proto_mode) { 10253 PrototypeOptimizationMode proto_mode) {
10186 if (map->prototype()->IsJSObject() && FLAG_track_prototype_users) {
10187 Handle<JSObject> old_prototype(JSObject::cast(map->prototype()));
10188 JSObject::UnregisterPrototypeUser(old_prototype, map);
10189 }
10190 if (prototype->IsJSObject()) { 10254 if (prototype->IsJSObject()) {
10191 Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype); 10255 Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
10192 JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode); 10256 JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
10193 if (ShouldRegisterAsPrototypeUser(map, prototype_jsobj)) {
10194 JSObject::RegisterPrototypeUser(prototype_jsobj, map);
10195 }
10196 } 10257 }
10197 WriteBarrierMode wb_mode = 10258 WriteBarrierMode wb_mode =
10198 prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; 10259 prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
10199 map->set_prototype(*prototype, wb_mode); 10260 map->set_prototype(*prototype, wb_mode);
10200 } 10261 }
10201 10262
10202 10263
10203 // static
10204 bool Map::ShouldRegisterAsPrototypeUser(Handle<Map> map,
10205 Handle<JSObject> prototype) {
10206 if (!FLAG_track_prototype_users) return false;
10207 if (map->is_prototype_map()) return true;
10208 Object* back = map->GetBackPointer();
10209 if (!back->IsMap()) return true;
10210 if (Map::cast(back)->prototype() != *prototype) return true;
10211 return false;
10212 }
10213
10214
10215 Handle<Object> CacheInitialJSArrayMaps( 10264 Handle<Object> CacheInitialJSArrayMaps(
10216 Handle<Context> native_context, Handle<Map> initial_map) { 10265 Handle<Context> native_context, Handle<Map> initial_map) {
10217 // Replace all of the cached initial array maps in the native context with 10266 // Replace all of the cached initial array maps in the native context with
10218 // the appropriate transitioned elements kind maps. 10267 // the appropriate transitioned elements kind maps.
10219 Factory* factory = native_context->GetIsolate()->factory(); 10268 Factory* factory = native_context->GetIsolate()->factory();
10220 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles( 10269 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
10221 kElementsKindCount, TENURED); 10270 kElementsKindCount, TENURED);
10222 10271
10223 Handle<Map> current_map = initial_map; 10272 Handle<Map> current_map = initial_map;
10224 ElementsKind kind = current_map->elements_kind(); 10273 ElementsKind kind = current_map->elements_kind();
(...skipping 6898 matching lines...) Expand 10 before | Expand all | Expand 10 after
17123 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell, 17172 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell,
17124 Handle<Object> new_value) { 17173 Handle<Object> new_value) {
17125 if (cell->value() != *new_value) { 17174 if (cell->value() != *new_value) {
17126 cell->set_value(*new_value); 17175 cell->set_value(*new_value);
17127 Isolate* isolate = cell->GetIsolate(); 17176 Isolate* isolate = cell->GetIsolate();
17128 cell->dependent_code()->DeoptimizeDependentCodeGroup( 17177 cell->dependent_code()->DeoptimizeDependentCodeGroup(
17129 isolate, DependentCode::kPropertyCellChangedGroup); 17178 isolate, DependentCode::kPropertyCellChangedGroup);
17130 } 17179 }
17131 } 17180 }
17132 } } // namespace v8::internal 17181 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | test/cctest/test-heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698