Commit fdaa6c28 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

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/+/2245591Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68530}
parent 42398807
...@@ -4395,6 +4395,12 @@ void InvalidateOnePrototypeValidityCellInternal(Map map) { ...@@ -4395,6 +4395,12 @@ void InvalidateOnePrototypeValidityCellInternal(Map map) {
} }
void InvalidatePrototypeChainsInternal(Map map) { void InvalidatePrototypeChainsInternal(Map 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); InvalidateOnePrototypeValidityCellInternal(map);
Object maybe_proto_info = map.prototype_info(); Object maybe_proto_info = map.prototype_info();
...@@ -4406,15 +4412,21 @@ void InvalidatePrototypeChainsInternal(Map map) { ...@@ -4406,15 +4412,21 @@ void InvalidatePrototypeChainsInternal(Map map) {
WeakArrayList prototype_users = WeakArrayList prototype_users =
WeakArrayList::cast(proto_info.prototype_users()); WeakArrayList::cast(proto_info.prototype_users());
// For now, only maps register themselves as users. // For now, only maps register themselves as users.
for (int i = PrototypeUsers::kFirstIndex; i < prototype_users.length(); ++i) { for (int i = PrototypeUsers::kFirstIndex; i < prototype_users.length();
++i) {
HeapObject heap_object; HeapObject heap_object;
if (prototype_users.Get(i)->GetHeapObjectIfWeak(&heap_object) && if (prototype_users.Get(i)->GetHeapObjectIfWeak(&heap_object) &&
heap_object.IsMap()) { heap_object.IsMap()) {
// Walk the prototype chain (backwards, towards leaf objects) if // Walk the prototype chain (backwards, towards leaf objects) if
// necessary. // necessary.
if (next_map.is_null()) {
next_map = Map::cast(heap_object);
} else {
InvalidatePrototypeChainsInternal(Map::cast(heap_object)); InvalidatePrototypeChainsInternal(Map::cast(heap_object));
} }
} }
}
}
} }
} // namespace } // namespace
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment