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

Side by Side Diff: src/objects.cc

Issue 1108583002: Revert of Lazily register prototype users (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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 1918 matching lines...) Expand 10 before | Expand all | Expand 10 after
1929 MigrateFastToSlow(object, new_map, expected_additional_properties); 1929 MigrateFastToSlow(object, new_map, expected_additional_properties);
1930 } 1930 }
1931 } else { 1931 } else {
1932 // For slow-to-fast migrations JSObject::MigrateSlowToFast() 1932 // For slow-to-fast migrations JSObject::MigrateSlowToFast()
1933 // must be used instead. 1933 // must be used instead.
1934 CHECK(new_map->is_dictionary_map()); 1934 CHECK(new_map->is_dictionary_map());
1935 1935
1936 // Slow-to-slow migration is trivial. 1936 // Slow-to-slow migration is trivial.
1937 object->set_map(*new_map); 1937 object->set_map(*new_map);
1938 } 1938 }
1939 if (old_map->is_prototype_map() && FLAG_track_prototype_users) { 1939 if (old_map->is_prototype_map()) {
1940 DCHECK(new_map->is_prototype_map()); 1940 DCHECK(new_map->is_prototype_map());
1941 DCHECK(object->map() == *new_map); 1941 DCHECK(object->map() == *new_map);
1942 new_map->set_prototype_info(old_map->prototype_info()); 1942 new_map->set_prototype_info(old_map->prototype_info());
1943 old_map->set_prototype_info(Smi::FromInt(0)); 1943 old_map->set_prototype_info(Smi::FromInt(0));
1944 if (FLAG_trace_prototype_users) { 1944 if (FLAG_trace_prototype_users) {
1945 PrintF("Moving prototype_info %p from map %p to map %p.\n", 1945 PrintF("Moving prototype_info %p from map %p to map %p.\n",
1946 reinterpret_cast<void*>(new_map->prototype_info()), 1946 reinterpret_cast<void*>(new_map->prototype_info()),
1947 reinterpret_cast<void*>(*old_map), 1947 reinterpret_cast<void*>(*old_map),
1948 reinterpret_cast<void*>(*new_map)); 1948 reinterpret_cast<void*>(*new_map));
1949 } 1949 }
1950 // If the map was registered with its prototype before, ensure that it
1951 // registers with its new prototype now. This preserves the invariant that
1952 // when a map on a prototype chain is registered with its prototype, then
1953 // all prototypes further up the chain are also registered with their
1954 // respective prototypes.
1955 Object* maybe_old_prototype = old_map->prototype();
1956 if (maybe_old_prototype->IsJSObject()) {
1957 Handle<JSObject> old_prototype(JSObject::cast(maybe_old_prototype));
1958 bool was_registered =
1959 JSObject::UnregisterPrototypeUser(old_prototype, old_map);
1960 if (was_registered) {
1961 JSObject::LazyRegisterPrototypeUser(new_map, new_map->GetIsolate());
1962 }
1963 }
1964 } 1950 }
1965 } 1951 }
1966 1952
1967 1953
1968 // To migrate a fast instance to a fast map: 1954 // To migrate a fast instance to a fast map:
1969 // - First check whether the instance needs to be rewritten. If not, simply 1955 // - First check whether the instance needs to be rewritten. If not, simply
1970 // change the map. 1956 // change the map.
1971 // - Otherwise, allocate a fixed array large enough to hold all fields, in 1957 // - Otherwise, allocate a fixed array large enough to hold all fields, in
1972 // addition to unused space. 1958 // addition to unused space.
1973 // - Copy all existing properties in, in the following order: backing store 1959 // - Copy all existing properties in, in the following order: backing store
(...skipping 5119 matching lines...) Expand 10 before | Expand all | Expand 10 after
7093 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, 7079 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
7094 Handle<Name> name, SimpleTransitionFlag flag) { 7080 Handle<Name> name, SimpleTransitionFlag flag) {
7095 parent->set_owns_descriptors(false); 7081 parent->set_owns_descriptors(false);
7096 if (parent->is_prototype_map()) { 7082 if (parent->is_prototype_map()) {
7097 DCHECK(child->is_prototype_map()); 7083 DCHECK(child->is_prototype_map());
7098 #if TRACE_MAPS 7084 #if TRACE_MAPS
7099 Map::TraceTransition("NoTransition", *parent, *child, *name); 7085 Map::TraceTransition("NoTransition", *parent, *child, *name);
7100 #endif 7086 #endif
7101 } else { 7087 } else {
7102 TransitionArray::Insert(parent, name, child, flag); 7088 TransitionArray::Insert(parent, name, child, flag);
7089 if (child->prototype()->IsJSObject()) {
7090 Handle<JSObject> proto(JSObject::cast(child->prototype()));
7091 if (!ShouldRegisterAsPrototypeUser(child, proto)) {
7092 JSObject::UnregisterPrototypeUser(proto, child);
7093 }
7094 }
7103 #if TRACE_MAPS 7095 #if TRACE_MAPS
7104 Map::TraceTransition("Transition", *parent, *child, *name); 7096 Map::TraceTransition("Transition", *parent, *child, *name);
7105 #endif 7097 #endif
7106 } 7098 }
7107 } 7099 }
7108 7100
7109 7101
7110 Handle<Map> Map::CopyReplaceDescriptors( 7102 Handle<Map> Map::CopyReplaceDescriptors(
7111 Handle<Map> map, Handle<DescriptorArray> descriptors, 7103 Handle<Map> map, Handle<DescriptorArray> descriptors,
7112 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag, 7104 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
(...skipping 1144 matching lines...) Expand 10 before | Expand all | Expand 10 after
8257 if (FLAG_trace_weak_arrays) { 8249 if (FLAG_trace_weak_arrays) {
8258 PrintF("[WeakFixedArray: storing at index %d ]\n", index); 8250 PrintF("[WeakFixedArray: storing at index %d ]\n", index);
8259 } 8251 }
8260 array->set_last_used_index(index); 8252 array->set_last_used_index(index);
8261 } 8253 }
8262 8254
8263 8255
8264 // static 8256 // static
8265 Handle<WeakFixedArray> WeakFixedArray::Add( 8257 Handle<WeakFixedArray> WeakFixedArray::Add(
8266 Handle<Object> maybe_array, Handle<HeapObject> value, 8258 Handle<Object> maybe_array, Handle<HeapObject> value,
8267 SearchForDuplicates search_for_duplicates, bool* was_present) { 8259 SearchForDuplicates search_for_duplicates) {
8268 Handle<WeakFixedArray> array = 8260 Handle<WeakFixedArray> array =
8269 (maybe_array.is_null() || !maybe_array->IsWeakFixedArray()) 8261 (maybe_array.is_null() || !maybe_array->IsWeakFixedArray())
8270 ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null()) 8262 ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null())
8271 : Handle<WeakFixedArray>::cast(maybe_array); 8263 : Handle<WeakFixedArray>::cast(maybe_array);
8272 if (was_present != NULL) *was_present = false; 8264
8273 if (search_for_duplicates == kAddIfNotFound) { 8265 if (search_for_duplicates == kAddIfNotFound) {
8274 for (int i = 0; i < array->Length(); ++i) { 8266 for (int i = 0; i < array->Length(); ++i) {
8275 if (array->Get(i) == *value) { 8267 if (array->Get(i) == *value) return array;
8276 if (was_present != NULL) *was_present = true;
8277 return array;
8278 }
8279 } 8268 }
8280 #if 0 // Enable this if you want to check your search_for_duplicates flags. 8269 #if 0 // Enable this if you want to check your search_for_duplicates flags.
8281 } else { 8270 } else {
8282 for (int i = 0; i < array->Length(); ++i) { 8271 for (int i = 0; i < array->Length(); ++i) {
8283 DCHECK_NE(*value, array->Get(i)); 8272 DCHECK_NE(*value, array->Get(i));
8284 } 8273 }
8285 #endif 8274 #endif
8286 } 8275 }
8287 8276
8288 // Try to store the new entry if there's room. Optimize for consecutive 8277 // Try to store the new entry if there's room. Optimize for consecutive
8289 // accesses. 8278 // accesses.
8290 int first_index = array->last_used_index(); 8279 int first_index = array->last_used_index();
8291 if (array->Length() > 0) { 8280 for (int i = first_index;;) {
8292 for (int i = first_index;;) { 8281 if (array->IsEmptySlot((i))) {
8293 if (array->IsEmptySlot((i))) { 8282 WeakFixedArray::Set(array, i, value);
8294 WeakFixedArray::Set(array, i, value); 8283 return array;
8295 return array;
8296 }
8297 if (FLAG_trace_weak_arrays) {
8298 PrintF("[WeakFixedArray: searching for free slot]\n");
8299 }
8300 i = (i + 1) % array->Length();
8301 if (i == first_index) break;
8302 } 8284 }
8285 if (FLAG_trace_weak_arrays) {
8286 PrintF("[WeakFixedArray: searching for free slot]\n");
8287 }
8288 i = (i + 1) % array->Length();
8289 if (i == first_index) break;
8303 } 8290 }
8304 8291
8305 // No usable slot found, grow the array. 8292 // No usable slot found, grow the array.
8306 int new_length = 8293 int new_length = array->Length() + (array->Length() >> 1) + 4;
8307 array->Length() == 0 ? 1 : array->Length() + (array->Length() >> 1) + 4;
8308 Handle<WeakFixedArray> new_array = 8294 Handle<WeakFixedArray> new_array =
8309 Allocate(array->GetIsolate(), new_length, array); 8295 Allocate(array->GetIsolate(), new_length, array);
8310 if (FLAG_trace_weak_arrays) { 8296 if (FLAG_trace_weak_arrays) {
8311 PrintF("[WeakFixedArray: growing to size %d ]\n", new_length); 8297 PrintF("[WeakFixedArray: growing to size %d ]\n", new_length);
8312 } 8298 }
8313 WeakFixedArray::Set(new_array, array->Length(), value); 8299 WeakFixedArray::Set(new_array, array->Length(), value);
8314 return new_array; 8300 return new_array;
8315 } 8301 }
8316 8302
8317 8303
8318 void WeakFixedArray::Compact() { 8304 void WeakFixedArray::Compact() {
8319 FixedArray* array = FixedArray::cast(this); 8305 FixedArray* array = FixedArray::cast(this);
8320 int new_length = kFirstIndex; 8306 int new_length = kFirstIndex;
8321 for (int i = kFirstIndex; i < array->length(); i++) { 8307 for (int i = kFirstIndex; i < array->length(); i++) {
8322 Object* element = array->get(i); 8308 Object* element = array->get(i);
8323 if (element->IsSmi()) continue; 8309 if (element->IsSmi()) continue;
8324 if (WeakCell::cast(element)->cleared()) continue; 8310 if (WeakCell::cast(element)->cleared()) continue;
8325 array->set(new_length++, element); 8311 array->set(new_length++, element);
8326 } 8312 }
8327 array->Shrink(new_length); 8313 array->Shrink(new_length);
8328 set_last_used_index(0); 8314 set_last_used_index(0);
8329 } 8315 }
8330 8316
8331 8317
8332 bool WeakFixedArray::Remove(Handle<HeapObject> value) { 8318 void WeakFixedArray::Remove(Handle<HeapObject> value) {
8333 if (Length() == 0) return false;
8334 // Optimize for the most recently added element to be removed again. 8319 // Optimize for the most recently added element to be removed again.
8335 int first_index = last_used_index(); 8320 int first_index = last_used_index();
8336 for (int i = first_index;;) { 8321 for (int i = first_index;;) {
8337 if (Get(i) == *value) { 8322 if (Get(i) == *value) {
8338 clear(i); 8323 clear(i);
8339 // Users of WeakFixedArray should make sure that there are no duplicates, 8324 // Users of WeakFixedArray should make sure that there are no duplicates,
8340 // they can use Add(..., kAddIfNotFound) if necessary. 8325 // they can use Add(..., kAddIfNotFound) if necessary.
8341 return true; 8326 return;
8342 } 8327 }
8343 i = (i + 1) % Length(); 8328 i = (i + 1) % Length();
8344 if (i == first_index) return false; 8329 if (i == first_index) break;
8345 } 8330 }
8346 UNREACHABLE();
8347 } 8331 }
8348 8332
8349 8333
8350 // static 8334 // static
8351 Handle<WeakFixedArray> WeakFixedArray::Allocate( 8335 Handle<WeakFixedArray> WeakFixedArray::Allocate(
8352 Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) { 8336 Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) {
8353 DCHECK(0 <= size); 8337 DCHECK(0 <= size);
8354 Handle<FixedArray> result = 8338 Handle<FixedArray> result =
8355 isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex); 8339 isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex);
8356 Handle<WeakFixedArray> casted_result = Handle<WeakFixedArray>::cast(result); 8340 Handle<WeakFixedArray> casted_result = Handle<WeakFixedArray>::cast(result);
(...skipping 1712 matching lines...) Expand 10 before | Expand all | Expand 10 after
10069 10053
10070 10054
10071 // static 10055 // static
10072 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) { 10056 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
10073 if (!object->map()->is_prototype_map()) return; 10057 if (!object->map()->is_prototype_map()) return;
10074 OptimizeAsPrototype(object, FAST_PROTOTYPE); 10058 OptimizeAsPrototype(object, FAST_PROTOTYPE);
10075 } 10059 }
10076 10060
10077 10061
10078 // static 10062 // static
10079 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) { 10063 void JSObject::RegisterPrototypeUser(Handle<JSObject> prototype,
10064 Handle<HeapObject> user) {
10080 DCHECK(FLAG_track_prototype_users); 10065 DCHECK(FLAG_track_prototype_users);
10081 // Contract: In line with InvalidatePrototypeChains()'s requirements, 10066 Isolate* isolate = prototype->GetIsolate();
10082 // leaf maps don't need to register as users, only prototypes do. 10067 if (prototype->IsJSGlobalProxy()) {
10083 DCHECK(user->is_prototype_map()); 10068 PrototypeIterator iter(isolate, prototype);
10084 10069 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
10085 Handle<Map> current_user = user; 10070 }
10086 for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) { 10071 Handle<PrototypeInfo> proto_info;
10087 Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter); 10072 Object* maybe_proto_info = prototype->map()->prototype_info();
10088 if (maybe_proto->IsJSGlobalProxy()) continue; 10073 if (maybe_proto_info->IsPrototypeInfo()) {
10089 // Proxies on the prototype chain are not supported. 10074 proto_info = handle(PrototypeInfo::cast(maybe_proto_info), isolate);
10090 if (maybe_proto->IsJSProxy()) return; 10075 } else {
10091 Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto); 10076 proto_info = isolate->factory()->NewPrototypeInfo();
10092 bool just_registered = 10077 prototype->map()->set_prototype_info(*proto_info);
10093 RegisterPrototypeUserIfNotRegistered(proto, current_user, isolate); 10078 }
10094 // Walk up the prototype chain as far as links haven't been registered yet. 10079 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
10095 if (!just_registered) break; 10080 Handle<WeakFixedArray> new_array = WeakFixedArray::Add(maybe_registry, user);
10096 current_user = handle(proto->map(), isolate); 10081 if (!maybe_registry.is_identical_to(new_array)) {
10082 proto_info->set_prototype_users(*new_array);
10083 }
10084 if (FLAG_trace_prototype_users) {
10085 PrintF("Registering %p as a user of prototype %p.\n",
10086 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype));
10097 } 10087 }
10098 } 10088 }
10099 10089
10100 10090
10101 // Returns true if the user was not yet registered.
10102 // static 10091 // static
10103 bool JSObject::RegisterPrototypeUserIfNotRegistered(Handle<JSObject> prototype, 10092 void JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype,
10104 Handle<HeapObject> user,
10105 Isolate* isolate) {
10106 Handle<PrototypeInfo> proto_info =
10107 Map::GetOrCreatePrototypeInfo(prototype, isolate);
10108 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
10109 bool was_present = false;
10110 Handle<WeakFixedArray> new_array = WeakFixedArray::Add(
10111 maybe_registry, user, WeakFixedArray::kAddIfNotFound, &was_present);
10112 if (!maybe_registry.is_identical_to(new_array)) {
10113 proto_info->set_prototype_users(*new_array);
10114 }
10115 if (FLAG_trace_prototype_users && !was_present) {
10116 PrintF("Registering %p as a user of prototype %p (map=%p).\n",
10117 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype),
10118 reinterpret_cast<void*>(prototype->map()));
10119 }
10120 return !was_present;
10121 }
10122
10123
10124 // Can be called regardless of whether |user| was actually registered with
10125 // |prototype|. Returns true when there was a registration.
10126 // static
10127 bool JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype,
10128 Handle<HeapObject> user) { 10093 Handle<HeapObject> user) {
10129 Isolate* isolate = prototype->GetIsolate(); 10094 Isolate* isolate = prototype->GetIsolate();
10130 if (prototype->IsJSGlobalProxy()) { 10095 if (prototype->IsJSGlobalProxy()) {
10131 PrototypeIterator iter(isolate, prototype); 10096 PrototypeIterator iter(isolate, prototype);
10132 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); 10097 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
10133 } 10098 }
10134 DCHECK(prototype->map()->is_prototype_map()); 10099 DCHECK(prototype->map()->is_prototype_map());
10135 Object* maybe_proto_info = prototype->map()->prototype_info(); 10100 Object* maybe_proto_info = prototype->map()->prototype_info();
10136 if (!maybe_proto_info->IsPrototypeInfo()) return false; 10101 if (!maybe_proto_info->IsPrototypeInfo()) return;
10137 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info), 10102 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
10138 isolate); 10103 isolate);
10139 Object* maybe_registry = proto_info->prototype_users(); 10104 Object* maybe_registry = proto_info->prototype_users();
10140 if (!maybe_registry->IsWeakFixedArray()) return false; 10105 if (!maybe_registry->IsWeakFixedArray()) return;
10141 bool result = WeakFixedArray::cast(maybe_registry)->Remove(user); 10106 WeakFixedArray::cast(maybe_registry)->Remove(user);
10142 if (FLAG_trace_prototype_users && result) { 10107 if (FLAG_trace_prototype_users) {
10143 PrintF("Unregistering %p as a user of prototype %p.\n", 10108 PrintF("Unregistering %p as a user of prototype %p.\n",
10144 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype)); 10109 reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype));
10145 } 10110 }
10146 return result;
10147 } 10111 }
10148 10112
10149 10113
10150 static void InvalidatePrototypeChainsInternal(Map* map) { 10114 static void InvalidatePrototypeChainsInternal(Map* map) {
10151 if (!map->is_prototype_map()) return; 10115 if (!map->is_prototype_map()) return;
10152 if (FLAG_trace_prototype_users) {
10153 PrintF("Invalidating prototype map %p 's cell\n",
10154 reinterpret_cast<void*>(map));
10155 }
10156 Object* maybe_proto_info = map->prototype_info(); 10116 Object* maybe_proto_info = map->prototype_info();
10157 if (!maybe_proto_info->IsPrototypeInfo()) return; 10117 if (!maybe_proto_info->IsPrototypeInfo()) return;
10158 PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info); 10118 PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info);
10159 Object* maybe_cell = proto_info->validity_cell(); 10119 Object* maybe_cell = proto_info->validity_cell();
10160 if (maybe_cell->IsCell()) { 10120 if (maybe_cell->IsCell()) {
10161 // Just set the value; the cell will be replaced lazily. 10121 // Just set the value; the cell will be replaced lazily.
10162 Cell* cell = Cell::cast(maybe_cell); 10122 Cell* cell = Cell::cast(maybe_cell);
10163 cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid)); 10123 cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
10164 } 10124 }
10165 10125
(...skipping 18 matching lines...) Expand all
10184 if (!FLAG_eliminate_prototype_chain_checks) return; 10144 if (!FLAG_eliminate_prototype_chain_checks) return;
10185 DisallowHeapAllocation no_gc; 10145 DisallowHeapAllocation no_gc;
10186 if (map->IsJSGlobalProxyMap()) { 10146 if (map->IsJSGlobalProxyMap()) {
10187 PrototypeIterator iter(map); 10147 PrototypeIterator iter(map);
10188 map = JSObject::cast(iter.GetCurrent())->map(); 10148 map = JSObject::cast(iter.GetCurrent())->map();
10189 } 10149 }
10190 InvalidatePrototypeChainsInternal(map); 10150 InvalidatePrototypeChainsInternal(map);
10191 } 10151 }
10192 10152
10193 10153
10194 // static
10195 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
10196 Isolate* isolate) {
10197 Object* maybe_proto_info = prototype->map()->prototype_info();
10198 if (maybe_proto_info->IsPrototypeInfo()) {
10199 return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
10200 }
10201 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
10202 prototype->map()->set_prototype_info(*proto_info);
10203 return proto_info;
10204 }
10205
10206
10207 // static 10154 // static
10208 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, 10155 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
10209 Isolate* isolate) { 10156 Isolate* isolate) {
10210 Handle<Object> maybe_prototype(map->prototype(), isolate); 10157 Handle<Object> maybe_prototype(map->prototype(), isolate);
10211 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null(); 10158 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null();
10212 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype); 10159 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
10213 if (prototype->IsJSGlobalProxy()) { 10160 if (prototype->IsJSGlobalProxy()) {
10214 PrototypeIterator iter(isolate, prototype); 10161 PrototypeIterator iter(isolate, prototype);
10215 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); 10162 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
10216 } 10163 }
10217 // Ensure the prototype is registered with its own prototypes so its cell 10164 Handle<PrototypeInfo> proto_info(
10218 // will be invalidated when necessary. 10165 PrototypeInfo::cast(prototype->map()->prototype_info()), isolate);
10219 JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
10220 isolate);
10221 Handle<PrototypeInfo> proto_info =
10222 GetOrCreatePrototypeInfo(prototype, isolate);
10223 Object* maybe_cell = proto_info->validity_cell(); 10166 Object* maybe_cell = proto_info->validity_cell();
10224 // Return existing cell if it's still valid. 10167 // Return existing cell if it's still valid.
10225 if (maybe_cell->IsCell()) { 10168 if (maybe_cell->IsCell()) {
10226 Handle<Cell> cell(Cell::cast(maybe_cell), isolate); 10169 Handle<Cell> cell(Cell::cast(maybe_cell), isolate);
10227 if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) { 10170 if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) {
10228 return cell; 10171 return handle(Cell::cast(maybe_cell), isolate);
10229 } 10172 }
10230 } 10173 }
10231 // Otherwise create a new cell. 10174 // Otherwise create a new cell.
10232 Handle<Cell> cell = isolate->factory()->NewCell( 10175 Handle<Cell> cell = isolate->factory()->NewCell(
10233 handle(Smi::FromInt(Map::kPrototypeChainValid), isolate)); 10176 handle(Smi::FromInt(Map::kPrototypeChainValid), isolate));
10234 proto_info->set_validity_cell(*cell); 10177 proto_info->set_validity_cell(*cell);
10235 return cell; 10178 return cell;
10236 } 10179 }
10237 10180
10238 10181
10239 // static
10240 void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype, 10182 void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype,
10241 PrototypeOptimizationMode proto_mode) { 10183 PrototypeOptimizationMode proto_mode) {
10184 if (map->prototype()->IsJSObject() && FLAG_track_prototype_users) {
10185 Handle<JSObject> old_prototype(JSObject::cast(map->prototype()));
10186 JSObject::UnregisterPrototypeUser(old_prototype, map);
10187 }
10242 if (prototype->IsJSObject()) { 10188 if (prototype->IsJSObject()) {
10243 Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype); 10189 Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
10244 JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode); 10190 JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
10191 if (ShouldRegisterAsPrototypeUser(map, prototype_jsobj)) {
10192 JSObject::RegisterPrototypeUser(prototype_jsobj, map);
10193 }
10245 } 10194 }
10246 WriteBarrierMode wb_mode = 10195 WriteBarrierMode wb_mode =
10247 prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; 10196 prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
10248 map->set_prototype(*prototype, wb_mode); 10197 map->set_prototype(*prototype, wb_mode);
10249 } 10198 }
10250 10199
10251 10200
10201 // static
10202 bool Map::ShouldRegisterAsPrototypeUser(Handle<Map> map,
10203 Handle<JSObject> prototype) {
10204 if (!FLAG_track_prototype_users) return false;
10205 if (map->is_prototype_map()) return true;
10206 Object* back = map->GetBackPointer();
10207 if (!back->IsMap()) return true;
10208 if (Map::cast(back)->prototype() != *prototype) return true;
10209 return false;
10210 }
10211
10212
10252 Handle<Object> CacheInitialJSArrayMaps( 10213 Handle<Object> CacheInitialJSArrayMaps(
10253 Handle<Context> native_context, Handle<Map> initial_map) { 10214 Handle<Context> native_context, Handle<Map> initial_map) {
10254 // Replace all of the cached initial array maps in the native context with 10215 // Replace all of the cached initial array maps in the native context with
10255 // the appropriate transitioned elements kind maps. 10216 // the appropriate transitioned elements kind maps.
10256 Factory* factory = native_context->GetIsolate()->factory(); 10217 Factory* factory = native_context->GetIsolate()->factory();
10257 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles( 10218 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
10258 kElementsKindCount, TENURED); 10219 kElementsKindCount, TENURED);
10259 10220
10260 Handle<Map> current_map = initial_map; 10221 Handle<Map> current_map = initial_map;
10261 ElementsKind kind = current_map->elements_kind(); 10222 ElementsKind kind = current_map->elements_kind();
(...skipping 6910 matching lines...) Expand 10 before | Expand all | Expand 10 after
17172 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell, 17133 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell,
17173 Handle<Object> new_value) { 17134 Handle<Object> new_value) {
17174 if (cell->value() != *new_value) { 17135 if (cell->value() != *new_value) {
17175 cell->set_value(*new_value); 17136 cell->set_value(*new_value);
17176 Isolate* isolate = cell->GetIsolate(); 17137 Isolate* isolate = cell->GetIsolate();
17177 cell->dependent_code()->DeoptimizeDependentCodeGroup( 17138 cell->dependent_code()->DeoptimizeDependentCodeGroup(
17178 isolate, DependentCode::kPropertyCellChangedGroup); 17139 isolate, DependentCode::kPropertyCellChangedGroup);
17179 } 17140 }
17180 } 17141 }
17181 } } // namespace v8::internal 17142 } } // 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