Bug 215673 - Make it possible to create a WeakPtr to Node and use it store assigned nodes in SlotAssignment
Summary: Make it possible to create a WeakPtr to Node and use it store assigned nodes ...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: DOM (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Ryosuke Niwa
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2020-08-19 17:18 PDT by Ryosuke Niwa
Modified: 2021-04-12 21:45 PDT (History)
15 users (show)

See Also:


Attachments
WIP (9.65 KB, patch)
2020-08-19 17:19 PDT, Ryosuke Niwa
no flags Details | Formatted Diff | Diff
Patch (12.10 KB, patch)
2020-08-25 18:51 PDT, Ryosuke Niwa
darin: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ryosuke Niwa 2020-08-19 17:18:20 PDT
We should be able to make WeakPtr to Node. Deploy that in SlotAssignment.
Comment 1 Ryosuke Niwa 2020-08-19 17:19:00 PDT
Created attachment 406891 [details]
WIP
Comment 2 Radar WebKit Bug Importer 2020-08-19 18:09:13 PDT
<rdar://problem/67440818>
Comment 3 Geoffrey Garen 2020-08-20 10:31:08 PDT
Is it OK to make all Nodes bigger? Or should we consider putting the WeakPtrFactory in RareData?
Comment 4 Ryosuke Niwa 2020-08-20 11:57:46 PDT
(In reply to Geoffrey Garen from comment #3)
> Is it OK to make all Nodes bigger? Or should we consider putting the
> WeakPtrFactory in RareData?

I don't think putting in RareData is a good idea because ElementRareData is pretty big and I doubt that WeakPtr would stay rare. I'm running memory tests with this change.

I don't think the size of Node really matters these days because most of memory usage is JS heap. But if we really wanted, we can share it with NodeRareData pointer in Node. So basically, we can have a single pointer either point to WeakReference or NodeRareData/ElementRareData. When we create NodeRareData, we can move it inside.
Comment 5 Ryosuke Niwa 2020-08-25 18:51:06 PDT
Created attachment 407257 [details]
Patch
Comment 6 Ryosuke Niwa 2020-08-25 18:51:18 PDT
Our internal perf tests seem to show that this patch is basically perf & memory neutral.
Comment 7 Darin Adler 2020-08-26 10:41:26 PDT
I’m surprised that making all text nodes bigger is memory neutral!
Comment 8 Darin Adler 2020-08-26 10:53:53 PDT
Comment on attachment 407257 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=407257&action=review

I’m going to say review+ but I am surprised that we can afford this much extra memory for every text node.

If we can afford this extra memory, then it seems like we can cut down the code size and complexity of accessibility code by taking advantage. AXObjectCache::remove has a lot of code in it to respond to the deletion of a node. Needs to remove it from each of many separate data structures have nodes as keys or values. AccessibilityNodeObject::m_node is a raw pointer that is nulled out by a hand-written WeakPtr implementation in a function named "detachRemoteParts".

> Source/WebCore/html/HTMLSlotElement.cpp:122
> +    for (const WeakPtr<Node>& nodePtr : *assignedNodes) {

auto&

> Source/WebCore/html/HTMLSlotElement.cpp:125
> +            ASSERT_NOT_REACHED();

Why can we assert this?

> Source/WebCore/html/HTMLSlotElement.cpp:157
> -    return assignedNodes->map([] (Node* node) { return makeRef(*node); });
> +
> +    Vector<Ref<Node>> nodes;
> +    nodes.reserveInitialCapacity(assignedNodes->size());
> +    for (auto& nodePtr : *assignedNodes) {
> +        auto* node = nodePtr.get();
> +        if (UNLIKELY(!node))
> +            continue;
> +        nodes.uncheckedAppend(*node);
> +    }
> +
> +    return nodes;

I’d like us to create a Vector::map variant that allows removal of the nodes during the mapping process. I included this feature in makeVector, although the design isn’t super-elegant, and have found it to often be useful.
Comment 9 Ryosuke Niwa 2020-08-26 17:10:21 PDT
(In reply to Darin Adler from comment #8)
> Comment on attachment 407257 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=407257&action=review
> 
> I’m going to say review+ but I am surprised that we can afford this much
> extra memory for every text node.

I'm sure it's using slightly more memory but these days JS heap & IO surfaces account for a much larger proportion of the memory.

> If we can afford this extra memory, then it seems like we can cut down the
> code size and complexity of accessibility code by taking advantage.
> AXObjectCache::remove has a lot of code in it to respond to the deletion of
> a node. Needs to remove it from each of many separate data structures have
> nodes as keys or values. AccessibilityNodeObject::m_node is a raw pointer
> that is nulled out by a hand-written WeakPtr implementation in a function
> named "detachRemoteParts".

Yeah, there is a lot of code that could be simplified once this patch lands.

> > Source/WebCore/html/HTMLSlotElement.cpp:122
> > +    for (const WeakPtr<Node>& nodePtr : *assignedNodes) {
> 
> auto&

Hm... I explicitly wanted to communicate the fact it's a weak pointer. I'd use auto& and rename the variable to nodeWeakPtr then.

> > Source/WebCore/html/HTMLSlotElement.cpp:125
> > +            ASSERT_NOT_REACHED();
> 
> Why can we assert this?

In theory, this should never happen. This assertion being hit would mean that we have a bug somewhere, which I don't believe it exist today.

> > Source/WebCore/html/HTMLSlotElement.cpp:157
> > -    return assignedNodes->map([] (Node* node) { return makeRef(*node); });
> > +
> > +    Vector<Ref<Node>> nodes;
> > +    nodes.reserveInitialCapacity(assignedNodes->size());
> > +    for (auto& nodePtr : *assignedNodes) {
> > +        auto* node = nodePtr.get();
> > +        if (UNLIKELY(!node))
> > +            continue;
> > +        nodes.uncheckedAppend(*node);
> > +    }
> > +
> > +    return nodes;
> 
> I’d like us to create a Vector::map variant that allows removal of the nodes
> during the mapping process. I included this feature in makeVector, although
> the design isn’t super-elegant, and have found it to often be useful.

Yes, my thoughts exactly. I didn't do it in this patch because I wanted to keep it easily revertible in the case it still causes a perf regression somewhere but I'd go work on that on a separate patch.
Comment 10 Ryosuke Niwa 2020-08-26 18:26:25 PDT
Committed r266212: <https://trac.webkit.org/changeset/266212>