Avoid some recursion in InvalidatePrototypeChains
We can walk linear prototype chains using iteration instead of recursion, reducing the likelihood (though not excluding the possibility) that large prototype-relation graphs will run into a stack overflow. This partial mitigation should be performance neutral. Bug: v8:10522 Change-Id: Ia266efe38a9cc52fe6ab2189066f45c4566f3596 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2245591 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/master@{#68530}
This commit is contained in:
parent
4239880777
commit
fdaa6c286e
@ -4395,24 +4395,36 @@ void InvalidateOnePrototypeValidityCellInternal(Map map) {
|
||||
}
|
||||
|
||||
void InvalidatePrototypeChainsInternal(Map map) {
|
||||
InvalidateOnePrototypeValidityCellInternal(map);
|
||||
// We handle linear prototype chains by looping, and multiple children
|
||||
// by recursion, in order to reduce the likelihood of running into stack
|
||||
// overflows. So, conceptually, the outer loop iterates the depth of the
|
||||
// prototype tree, and the inner loop iterates the breadth of a node.
|
||||
Map next_map;
|
||||
for (; !map.is_null(); map = next_map, next_map = Map()) {
|
||||
InvalidateOnePrototypeValidityCellInternal(map);
|
||||
|
||||
Object maybe_proto_info = map.prototype_info();
|
||||
if (!maybe_proto_info.IsPrototypeInfo()) return;
|
||||
PrototypeInfo proto_info = PrototypeInfo::cast(maybe_proto_info);
|
||||
if (!proto_info.prototype_users().IsWeakArrayList()) {
|
||||
return;
|
||||
}
|
||||
WeakArrayList prototype_users =
|
||||
WeakArrayList::cast(proto_info.prototype_users());
|
||||
// For now, only maps register themselves as users.
|
||||
for (int i = PrototypeUsers::kFirstIndex; i < prototype_users.length(); ++i) {
|
||||
HeapObject heap_object;
|
||||
if (prototype_users.Get(i)->GetHeapObjectIfWeak(&heap_object) &&
|
||||
heap_object.IsMap()) {
|
||||
// Walk the prototype chain (backwards, towards leaf objects) if
|
||||
// necessary.
|
||||
InvalidatePrototypeChainsInternal(Map::cast(heap_object));
|
||||
Object maybe_proto_info = map.prototype_info();
|
||||
if (!maybe_proto_info.IsPrototypeInfo()) return;
|
||||
PrototypeInfo proto_info = PrototypeInfo::cast(maybe_proto_info);
|
||||
if (!proto_info.prototype_users().IsWeakArrayList()) {
|
||||
return;
|
||||
}
|
||||
WeakArrayList prototype_users =
|
||||
WeakArrayList::cast(proto_info.prototype_users());
|
||||
// For now, only maps register themselves as users.
|
||||
for (int i = PrototypeUsers::kFirstIndex; i < prototype_users.length();
|
||||
++i) {
|
||||
HeapObject heap_object;
|
||||
if (prototype_users.Get(i)->GetHeapObjectIfWeak(&heap_object) &&
|
||||
heap_object.IsMap()) {
|
||||
// Walk the prototype chain (backwards, towards leaf objects) if
|
||||
// necessary.
|
||||
if (next_map.is_null()) {
|
||||
next_map = Map::cast(heap_object);
|
||||
} else {
|
||||
InvalidatePrototypeChainsInternal(Map::cast(heap_object));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user