⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 280718 in webkit


Ignore:
Timestamp:
Aug 5, 2021, 8:10:40 PM (5 years ago)
Author:
Cameron McCormack
Message:

Stop tracking form elements with FormController
https://bugs.webkit.org/show_bug.cgi?id=228724
<rdar://problem/81435095>

Reviewed by Darin Adler.

Source/WebCore:

FormController currently tracks the insertion order of
HTMLFormElementWithState objects in the document. But we don't need
to know this list of form controls until the time we need to save
form state for the document (e.g. on pagehide). So we instead
traverse the document to find those elements at the point we need
them, rather than maintain FormController::m_formElementsWithState.

This is a small speedup (1-2%) on a few of the Speedometer subtests
that insert and remove many input elements.

A future optimization could record on the Document whether there are
any input elements that have had their value changed, since it's
probably common for pages with form controls to never be changed.

  • dom/Document.cpp:

(WebCore::Document::formElementsState const): Traverse the document to
find all the HTMLFormElementWithState objects.

  • dom/Element.h:

(WebCore::Element::isFormControlElementWithState const):

  • html/FormController.cpp:

(WebCore::FormController::createSavedFormStateMap):
(WebCore::FormController::formElementsState const):

  • html/FormController.h:
  • html/HTMLFormControlElementWithState.cpp:

(WebCore::HTMLFormControlElementWithState::insertedIntoAncestor):
Track the order that HTMLFormControlElementWithState objects are
inserted into the document.
(WebCore::HTMLFormControlElementWithState::removedFromAncestor):

  • html/HTMLFormControlElementWithState.h:

(WebCore::HTMLFormControlElementWithState::insertionIndex const):
(isType):

  • page/Frame.h: Remove unused formElementsCharacterCount.
  • page/ios/FrameIOS.mm:

Source/WebKitLegacy/mac:

formElementsCharacterCount is unused and can be removed.

  • WebView/WebFrame.mm:
  • WebView/WebFramePrivate.h:
Location:
trunk/Source
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r280715 r280718  
     12021-08-05  Cameron McCormack  <heycam@apple.com>
     2
     3        Stop tracking form elements with FormController
     4        https://bugs.webkit.org/show_bug.cgi?id=228724
     5        <rdar://problem/81435095>
     6
     7        Reviewed by Darin Adler.
     8
     9        FormController currently tracks the insertion order of
     10        HTMLFormElementWithState objects in the document.  But we don't need
     11        to know this list of form controls until the time we need to save
     12        form state for the document (e.g. on pagehide).  So we instead
     13        traverse the document to find those elements at the point we need
     14        them, rather than maintain FormController::m_formElementsWithState.
     15
     16        This is a small speedup (1-2%) on a few of the Speedometer subtests
     17        that insert and remove many input elements.
     18
     19        A future optimization could record on the Document whether there are
     20        any input elements that have had their value changed, since it's
     21        probably common for pages with form controls to never be changed.
     22
     23        * dom/Document.cpp:
     24        (WebCore::Document::formElementsState const): Traverse the document to
     25        find all the HTMLFormElementWithState objects.
     26        * dom/Element.h:
     27        (WebCore::Element::isFormControlElementWithState const):
     28        * html/FormController.cpp:
     29        (WebCore::FormController::createSavedFormStateMap):
     30        (WebCore::FormController::formElementsState const):
     31        * html/FormController.h:
     32        * html/HTMLFormControlElementWithState.cpp:
     33        (WebCore::HTMLFormControlElementWithState::insertedIntoAncestor):
     34        Track the order that HTMLFormControlElementWithState objects are
     35        inserted into the document.
     36        (WebCore::HTMLFormControlElementWithState::removedFromAncestor):
     37        * html/HTMLFormControlElementWithState.h:
     38        (WebCore::HTMLFormControlElementWithState::insertionIndex const):
     39        (isType):
     40        * page/Frame.h: Remove unused formElementsCharacterCount.
     41        * page/ios/FrameIOS.mm:
     42
    1432021-08-05  Tim Horton  <timothy_horton@apple.com>
    244
  • trunk/Source/WebCore/dom/Document.cpp

    r280700 r280718  
    19101910    if (!m_formController)
    19111911        return Vector<String>();
    1912     return m_formController->formElementsState();
     1912    return m_formController->formElementsState(*this);
    19131913}
    19141914
  • trunk/Source/WebCore/dom/Element.h

    r279054 r280718  
    469469
    470470    virtual bool isFormControlElement() const { return false; }
     471    virtual bool isFormControlElementWithState() const { return false; }
    471472    virtual bool isSpinButtonElement() const { return false; }
    472473    virtual bool isTextFormControlElement() const { return false; }
  • trunk/Source/WebCore/html/FormController.cpp

    r279439 r280718  
    343343FormController::~FormController() = default;
    344344
    345 unsigned FormController::formElementsCharacterCount() const
    346 {
    347     unsigned count = 0;
    348     for (auto& element : m_formElementsWithState) {
    349         if (element->isTextField())
    350             count += element->saveFormControlState()[0].length();
    351     }
    352     return count;
    353 }
    354 
    355345static String formStateSignature()
    356346{
     
    362352}
    363353
    364 std::unique_ptr<FormController::SavedFormStateMap> FormController::createSavedFormStateMap(const FormElementListHashSet& controlList)
     354std::unique_ptr<FormController::SavedFormStateMap> FormController::createSavedFormStateMap(const FormControlVector& controlList)
    365355{
    366356    FormKeyGenerator keyGenerator;
    367357    auto stateMap = makeUnique<SavedFormStateMap>();
    368     for (auto& control : controlList) {
    369         if (!control->shouldSaveAndRestoreFormControlState())
    370             continue;
    371         auto& formState = stateMap->add(keyGenerator.formKey(*control).impl(), nullptr).iterator->value;
     358    for (const HTMLFormControlElementWithState& control : controlList) {
     359        if (!control.shouldSaveAndRestoreFormControlState())
     360            continue;
     361        auto& formState = stateMap->add(keyGenerator.formKey(control).impl(), nullptr).iterator->value;
    372362        if (!formState)
    373363            formState = makeUnique<SavedFormState>();
    374         formState->appendControlState(control->name(), control->type(), control->saveFormControlState());
     364        formState->appendControlState(control.name(), control.type(), control.saveFormControlState());
    375365    }
    376366    return stateMap;
    377367}
    378368
    379 Vector<String> FormController::formElementsState() const
    380 {
    381     std::unique_ptr<SavedFormStateMap> stateMap = createSavedFormStateMap(m_formElementsWithState);
     369Vector<String> FormController::formElementsState(const Document& document) const
     370{
     371    // FIXME: We should be saving the state of form controls in shadow trees, too.
     372    FormControlVector controls;
     373    for (auto& control : descendantsOfType<HTMLFormControlElementWithState>(document)) {
     374        ASSERT(control.insertionIndex());
     375        controls.append(control);
     376    }
     377
     378    std::sort(controls.begin(), controls.end(), [](auto a, auto b) {
     379        return a.get().insertionIndex() < b.get().insertionIndex();
     380    });
     381
     382    auto stateMap = createSavedFormStateMap(controls);
    382383    Vector<String> stateVector;
    383     stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 4);
     384    stateVector.reserveInitialCapacity(controls.size() * 4);
    384385    stateVector.append(formStateSignature());
    385386    for (auto& state : *stateMap) {
     
    485486}
    486487
    487 void FormController::registerFormElementWithState(HTMLFormControlElementWithState& control)
    488 {
    489     ASSERT(!m_formElementsWithState.contains(&control));
    490     m_formElementsWithState.add(&control);
    491 }
    492 
    493 void FormController::unregisterFormElementWithState(HTMLFormControlElementWithState& control)
    494 {
    495     ASSERT(m_formElementsWithState.contains(&control));
    496     m_formElementsWithState.remove(&control);
    497 }
    498 
    499488} // namespace WebCore
  • trunk/Source/WebCore/html/FormController.h

    r250708 r280718  
    4343    ~FormController();
    4444
    45     void registerFormElementWithState(HTMLFormControlElementWithState&);
    46     void unregisterFormElementWithState(HTMLFormControlElementWithState&);
    47 
    48     unsigned formElementsCharacterCount() const;
    49 
    50     Vector<String> formElementsState() const;
     45    Vector<String> formElementsState(const Document&) const;
    5146    void setStateForNewFormElements(const Vector<String>&);
    5247
     
    5954
    6055private:
    61     typedef ListHashSet<RefPtr<HTMLFormControlElementWithState>> FormElementListHashSet;
    62     typedef HashMap<RefPtr<AtomStringImpl>, std::unique_ptr<SavedFormState>> SavedFormStateMap;
     56    using FormControlVector = Vector<std::reference_wrapper<const HTMLFormControlElementWithState>>;
     57    using SavedFormStateMap = HashMap<RefPtr<AtomStringImpl>, std::unique_ptr<SavedFormState>>;
    6358
    64     static std::unique_ptr<SavedFormStateMap> createSavedFormStateMap(const FormElementListHashSet&);
     59    static std::unique_ptr<SavedFormStateMap> createSavedFormStateMap(const FormControlVector&);
    6560    FormControlState takeStateForFormElement(const HTMLFormControlElementWithState&);
    6661    static void formStatesFromStateVector(const Vector<String>&, SavedFormStateMap&);
    6762
    68     FormElementListHashSet m_formElementsWithState;
    6963    SavedFormStateMap m_savedFormStateMap;
    7064    std::unique_ptr<FormKeyGenerator> m_formKeyGenerator;
  • trunk/Source/WebCore/html/HTMLFormControlElementWithState.cpp

    r229694 r280718  
    4444Node::InsertedIntoAncestorResult HTMLFormControlElementWithState::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
    4545{
    46     if (insertionType.connectedToDocument && !containingShadowRoot())
    47         document().formController().registerFormElementWithState(*this);
     46    m_insertionIndex = ++lastInsertionIndex;
    4847    return HTMLFormControlElement::insertedIntoAncestor(insertionType, parentOfInsertedTree);
    4948}
     
    5150void HTMLFormControlElementWithState::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
    5251{
    53     if (removalType.disconnectedFromDocument && !containingShadowRoot() && !oldParentOfRemovedTree.containingShadowRoot())
    54         document().formController().unregisterFormElementWithState(*this);
     52    m_insertionIndex = 0;
    5553    HTMLFormControlElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
    5654}
     
    8583}
    8684
     85uint64_t HTMLFormControlElementWithState::lastInsertionIndex { 0 };
     86
    8787} // namespace Webcore
  • trunk/Source/WebCore/html/HTMLFormControlElementWithState.h

    r229694 r280718  
    3939    virtual void restoreFormControlState(const FormControlState&) { } // Called only if state is not empty.
    4040
     41    uint64_t insertionIndex() const { return m_insertionIndex; }
     42
    4143protected:
    4244    HTMLFormControlElementWithState(const QualifiedName& tagName, Document&, HTMLFormElement*);
     
    5153private:
    5254    bool isFormControlElementWithState() const final;
     55
     56    uint64_t m_insertionIndex { 0 };
     57    static uint64_t lastInsertionIndex;
    5358};
    5459
     
    5661
    5762SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::HTMLFormControlElementWithState)
     63    static bool isType(const WebCore::Element& element) { return element.isFormControlElementWithState(); }
     64    static bool isType(const WebCore::Node& node) { return is<WebCore::Element>(node) && isType(downcast<WebCore::Element>(node)); }
    5865    static bool isType(const WebCore::FormAssociatedElement& element) { return element.isFormControlElementWithState(); }
    5966SPECIALIZE_TYPE_TRAITS_END()
  • trunk/Source/WebCore/page/Frame.h

    r280504 r280718  
    283283    WEBCORE_EXPORT NSRect caretRect();
    284284    WEBCORE_EXPORT NSRect rectForScrollToVisible();
    285     WEBCORE_EXPORT unsigned formElementsCharacterCount() const;
    286285
    287286    // This function is used by Legacy WebKit.
  • trunk/Source/WebCore/page/ios/FrameIOS.mm

    r279918 r280718  
    628628}
    629629
    630 unsigned Frame::formElementsCharacterCount() const
    631 {
    632     Document* document = this->document();
    633     if (!document)
    634         return 0;
    635     return document->formController().formElementsCharacterCount();
    636 }
    637 
    638630void Frame::setTimersPaused(bool paused)
    639631{
  • trunk/Source/WebKitLegacy/mac/ChangeLog

    r280467 r280718  
     12021-08-05  Cameron McCormack  <heycam@apple.com>
     2
     3        Stop tracking form elements with FormController
     4        https://bugs.webkit.org/show_bug.cgi?id=228724
     5        <rdar://problem/81435095>
     6
     7        Reviewed by Darin Adler.
     8
     9        formElementsCharacterCount is unused and can be removed.
     10
     11        * WebView/WebFrame.mm:
     12        * WebView/WebFramePrivate.h:
     13
    1142021-07-29  Myles C. Maxfield  <mmaxfield@apple.com>
    215
  • trunk/Source/WebKitLegacy/mac/WebView/WebFrame.mm

    r278542 r280718  
    11641164#if PLATFORM(IOS_FAMILY)
    11651165
    1166 - (unsigned)formElementsCharacterCount
    1167 {
    1168     return core(self)->formElementsCharacterCount();
    1169 }
    1170 
    11711166- (void)setTimeoutsPaused:(BOOL)flag
    11721167{
  • trunk/Source/WebKitLegacy/mac/WebView/WebFramePrivate.h

    r260366 r280718  
    9696- (void)_setLoadsSynchronously:(BOOL)flag;
    9797- (BOOL)_loadsSynchronously;
    98 - (unsigned)formElementsCharacterCount;
    9998- (void)setTimeoutsPaused:(BOOL)flag;
    10099
Note: See TracChangeset for help on using the changeset viewer.