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

Side by Side Diff: src/objects.cc

Issue 1559323002: [prototype user tracking] Don't skip JSGlobalProxies (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 11 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/mjsunit/regress/regress-crbug-571517.js » ('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 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 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 "src/objects.h" 5 #include "src/objects.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <iomanip> 8 #include <iomanip>
9 #include <sstream> 9 #include <sstream>
10 10
(...skipping 2661 matching lines...) Expand 10 before | Expand all | Expand 10 after
2672 DCHECK(target_inobject < GetInObjectProperties()); 2672 DCHECK(target_inobject < GetInObjectProperties());
2673 if (target_number_of_fields <= target_inobject) { 2673 if (target_number_of_fields <= target_inobject) {
2674 DCHECK(target_number_of_fields + target_unused == target_inobject); 2674 DCHECK(target_number_of_fields + target_unused == target_inobject);
2675 return false; 2675 return false;
2676 } 2676 }
2677 // Otherwise, properties will need to be moved to the backing store. 2677 // Otherwise, properties will need to be moved to the backing store.
2678 return true; 2678 return true;
2679 } 2679 }
2680 2680
2681 2681
2682 static void UpdatePrototypeUserRegistration(Handle<Map> old_map, 2682 // static
2683 Handle<Map> new_map, 2683 void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map,
2684 Isolate* isolate) { 2684 Handle<Map> new_map,
2685 Isolate* isolate) {
2685 if (!FLAG_track_prototype_users) return; 2686 if (!FLAG_track_prototype_users) return;
2686 if (!old_map->is_prototype_map()) return; 2687 if (!old_map->is_prototype_map()) return;
2687 DCHECK(new_map->is_prototype_map()); 2688 DCHECK(new_map->is_prototype_map());
2688 bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate); 2689 bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate);
2689 new_map->set_prototype_info(old_map->prototype_info()); 2690 new_map->set_prototype_info(old_map->prototype_info());
2690 old_map->set_prototype_info(Smi::FromInt(0)); 2691 old_map->set_prototype_info(Smi::FromInt(0));
2691 if (FLAG_trace_prototype_users) { 2692 if (FLAG_trace_prototype_users) {
2692 PrintF("Moving prototype_info %p from map %p to map %p.\n", 2693 PrintF("Moving prototype_info %p from map %p to map %p.\n",
2693 reinterpret_cast<void*>(new_map->prototype_info()), 2694 reinterpret_cast<void*>(new_map->prototype_info()),
2694 reinterpret_cast<void*>(*old_map), 2695 reinterpret_cast<void*>(*old_map),
(...skipping 9732 matching lines...) Expand 10 before | Expand all | Expand 10 after
12427 } 12428 }
12428 } 12429 }
12429 return false; 12430 return false;
12430 } 12431 }
12431 12432
12432 12433
12433 // static 12434 // static
12434 void JSObject::OptimizeAsPrototype(Handle<JSObject> object, 12435 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
12435 PrototypeOptimizationMode mode) { 12436 PrototypeOptimizationMode mode) {
12436 if (object->IsJSGlobalObject()) return; 12437 if (object->IsJSGlobalObject()) return;
12437 if (object->IsJSGlobalProxy()) return;
12438 if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) { 12438 if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) {
12439 // First normalize to ensure all JSFunctions are DATA_CONSTANT. 12439 // First normalize to ensure all JSFunctions are DATA_CONSTANT.
12440 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0, 12440 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
12441 "NormalizeAsPrototype"); 12441 "NormalizeAsPrototype");
12442 } 12442 }
12443 Handle<Map> previous_map(object->map()); 12443 Handle<Map> previous_map(object->map());
12444 if (!object->HasFastProperties()) { 12444 if (!object->HasFastProperties()) {
12445 JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype"); 12445 JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
12446 } 12446 }
12447 if (!object->map()->is_prototype_map()) { 12447 if (!object->map()->is_prototype_map()) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
12485 12485
12486 Handle<Map> current_user = user; 12486 Handle<Map> current_user = user;
12487 Handle<PrototypeInfo> current_user_info = 12487 Handle<PrototypeInfo> current_user_info =
12488 Map::GetOrCreatePrototypeInfo(user, isolate); 12488 Map::GetOrCreatePrototypeInfo(user, isolate);
12489 for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) { 12489 for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) {
12490 // Walk up the prototype chain as far as links haven't been registered yet. 12490 // Walk up the prototype chain as far as links haven't been registered yet.
12491 if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) { 12491 if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) {
12492 break; 12492 break;
12493 } 12493 }
12494 Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter); 12494 Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter);
12495 if (maybe_proto->IsJSGlobalProxy()) continue;
12496 // Proxies on the prototype chain are not supported. They make it 12495 // Proxies on the prototype chain are not supported. They make it
12497 // impossible to make any assumptions about the prototype chain anyway. 12496 // impossible to make any assumptions about the prototype chain anyway.
12498 if (maybe_proto->IsJSProxy()) return; 12497 if (maybe_proto->IsJSProxy()) return;
12499 Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto); 12498 Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto);
12500 Handle<PrototypeInfo> proto_info = 12499 Handle<PrototypeInfo> proto_info =
12501 Map::GetOrCreatePrototypeInfo(proto, isolate); 12500 Map::GetOrCreatePrototypeInfo(proto, isolate);
12502 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate); 12501 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
12503 int slot = 0; 12502 int slot = 0;
12504 Handle<WeakFixedArray> new_array = 12503 Handle<WeakFixedArray> new_array =
12505 WeakFixedArray::Add(maybe_registry, current_user, &slot); 12504 WeakFixedArray::Add(maybe_registry, current_user, &slot);
(...skipping 14 matching lines...) Expand all
12520 } 12519 }
12521 12520
12522 12521
12523 // Can be called regardless of whether |user| was actually registered with 12522 // Can be called regardless of whether |user| was actually registered with
12524 // |prototype|. Returns true when there was a registration. 12523 // |prototype|. Returns true when there was a registration.
12525 // static 12524 // static
12526 bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) { 12525 bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
12527 DCHECK(user->is_prototype_map()); 12526 DCHECK(user->is_prototype_map());
12528 // If it doesn't have a PrototypeInfo, it was never registered. 12527 // If it doesn't have a PrototypeInfo, it was never registered.
12529 if (!user->prototype_info()->IsPrototypeInfo()) return false; 12528 if (!user->prototype_info()->IsPrototypeInfo()) return false;
12530 // If it doesn't have a prototype, it can't be registered. 12529 // If it had no prototype before, see if it had users that might expect
12531 if (!user->prototype()->IsJSObject()) return false; 12530 // registration.
12531 if (!user->prototype()->IsJSObject()) {
12532 Object* users =
12533 PrototypeInfo::cast(user->prototype_info())->prototype_users();
12534 return users->IsWeakFixedArray();
12535 }
12532 Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate); 12536 Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate);
12533 Handle<PrototypeInfo> user_info = 12537 Handle<PrototypeInfo> user_info =
12534 Map::GetOrCreatePrototypeInfo(user, isolate); 12538 Map::GetOrCreatePrototypeInfo(user, isolate);
12535 int slot = user_info->registry_slot(); 12539 int slot = user_info->registry_slot();
12536 if (slot == PrototypeInfo::UNREGISTERED) return false; 12540 if (slot == PrototypeInfo::UNREGISTERED) return false;
12537 if (prototype->IsJSGlobalProxy()) {
12538 PrototypeIterator iter(isolate, prototype);
12539 prototype = PrototypeIterator::GetCurrent<JSObject>(iter);
12540 }
12541 DCHECK(prototype->map()->is_prototype_map()); 12541 DCHECK(prototype->map()->is_prototype_map());
12542 Object* maybe_proto_info = prototype->map()->prototype_info(); 12542 Object* maybe_proto_info = prototype->map()->prototype_info();
12543 // User knows its registry slot, prototype info and user registry must exist. 12543 // User knows its registry slot, prototype info and user registry must exist.
12544 DCHECK(maybe_proto_info->IsPrototypeInfo()); 12544 DCHECK(maybe_proto_info->IsPrototypeInfo());
12545 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info), 12545 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
12546 isolate); 12546 isolate);
12547 Object* maybe_registry = proto_info->prototype_users(); 12547 Object* maybe_registry = proto_info->prototype_users();
12548 DCHECK(maybe_registry->IsWeakFixedArray()); 12548 DCHECK(maybe_registry->IsWeakFixedArray());
12549 DCHECK(WeakFixedArray::cast(maybe_registry)->Get(slot) == *user); 12549 DCHECK(WeakFixedArray::cast(maybe_registry)->Get(slot) == *user);
12550 WeakFixedArray::cast(maybe_registry)->Clear(slot); 12550 WeakFixedArray::cast(maybe_registry)->Clear(slot);
(...skipping 28 matching lines...) Expand all
12579 // Walk the prototype chain (backwards, towards leaf objects) if necessary. 12579 // Walk the prototype chain (backwards, towards leaf objects) if necessary.
12580 InvalidatePrototypeChainsInternal(user); 12580 InvalidatePrototypeChainsInternal(user);
12581 } 12581 }
12582 } 12582 }
12583 12583
12584 12584
12585 // static 12585 // static
12586 void JSObject::InvalidatePrototypeChains(Map* map) { 12586 void JSObject::InvalidatePrototypeChains(Map* map) {
12587 if (!FLAG_eliminate_prototype_chain_checks) return; 12587 if (!FLAG_eliminate_prototype_chain_checks) return;
12588 DisallowHeapAllocation no_gc; 12588 DisallowHeapAllocation no_gc;
12589 if (map->IsJSGlobalProxyMap()) {
12590 PrototypeIterator iter(map);
12591 map = iter.GetCurrent<JSObject>()->map();
12592 }
12593 InvalidatePrototypeChainsInternal(map); 12589 InvalidatePrototypeChainsInternal(map);
12594 } 12590 }
12595 12591
12596 12592
12597 // static 12593 // static
12598 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype, 12594 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
12599 Isolate* isolate) { 12595 Isolate* isolate) {
12600 Object* maybe_proto_info = prototype->map()->prototype_info(); 12596 Object* maybe_proto_info = prototype->map()->prototype_info();
12601 if (maybe_proto_info->IsPrototypeInfo()) { 12597 if (maybe_proto_info->IsPrototypeInfo()) {
12602 return handle(PrototypeInfo::cast(maybe_proto_info), isolate); 12598 return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
(...skipping 16 matching lines...) Expand all
12619 return proto_info; 12615 return proto_info;
12620 } 12616 }
12621 12617
12622 12618
12623 // static 12619 // static
12624 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, 12620 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
12625 Isolate* isolate) { 12621 Isolate* isolate) {
12626 Handle<Object> maybe_prototype(map->prototype(), isolate); 12622 Handle<Object> maybe_prototype(map->prototype(), isolate);
12627 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null(); 12623 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null();
12628 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype); 12624 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
12629 if (prototype->IsJSGlobalProxy()) {
12630 PrototypeIterator iter(isolate, prototype);
12631 prototype = PrototypeIterator::GetCurrent<JSObject>(iter);
12632 }
12633 // Ensure the prototype is registered with its own prototypes so its cell 12625 // Ensure the prototype is registered with its own prototypes so its cell
12634 // will be invalidated when necessary. 12626 // will be invalidated when necessary.
12635 JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate), 12627 JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
12636 isolate); 12628 isolate);
12637 Handle<PrototypeInfo> proto_info = 12629 Handle<PrototypeInfo> proto_info =
12638 GetOrCreatePrototypeInfo(prototype, isolate); 12630 GetOrCreatePrototypeInfo(prototype, isolate);
12639 Object* maybe_cell = proto_info->validity_cell(); 12631 Object* maybe_cell = proto_info->validity_cell();
12640 // Return existing cell if it's still valid. 12632 // Return existing cell if it's still valid.
12641 if (maybe_cell->IsCell()) { 12633 if (maybe_cell->IsCell()) {
12642 Handle<Cell> cell(Cell::cast(maybe_cell), isolate); 12634 Handle<Cell> cell(Cell::cast(maybe_cell), isolate);
(...skipping 6850 matching lines...) Expand 10 before | Expand all | Expand 10 after
19493 if (cell->value() != *new_value) { 19485 if (cell->value() != *new_value) {
19494 cell->set_value(*new_value); 19486 cell->set_value(*new_value);
19495 Isolate* isolate = cell->GetIsolate(); 19487 Isolate* isolate = cell->GetIsolate();
19496 cell->dependent_code()->DeoptimizeDependentCodeGroup( 19488 cell->dependent_code()->DeoptimizeDependentCodeGroup(
19497 isolate, DependentCode::kPropertyCellChangedGroup); 19489 isolate, DependentCode::kPropertyCellChangedGroup);
19498 } 19490 }
19499 } 19491 }
19500 19492
19501 } // namespace internal 19493 } // namespace internal
19502 } // namespace v8 19494 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | test/mjsunit/regress/regress-crbug-571517.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698