Changeset 175852 in webkit
- Timestamp:
- Nov 10, 2014, 11:19:53 PM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 5 edited
-
ChangeLog (modified) (1 diff)
-
dom/Element.cpp (modified) (1 diff)
-
dom/Element.h (modified) (1 diff)
-
html/HTMLInputElement.cpp (modified) (7 diffs)
-
html/HTMLInputElement.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r175848 r175852 1 2014-11-10 Chris Dumez <cdumez@apple.com> 2 3 Lazily create HTMLInputElement's inputType and shadow subtree 4 https://bugs.webkit.org/show_bug.cgi?id=138524 5 6 Reviewed by Ryosuke Niwa. 7 8 When an HTMLInputElement was created by the parser, we would first call 9 HTMLInputElement::create(), then call Element::parserSetAttributes() on 10 the constructed input. With the previous implementation, this was a bit 11 inefficient because HTMLInputElement::create() would construct a 12 TextInputType inputType (as this is the default) as well as its 13 corresponding shadow subtree. Then, parserSetAttributes() would often 14 set the |type| attribute and would need to destroy this input type as 15 well as its subtree if the new |type| is not 'text', to create a new 16 inputType / shadow subtree of the right type. The profiler showed that 17 this was fairly expensive. 18 19 To improve this, this patch delays the inputType / shadow subtree 20 creation when the HTMLInputElement is constructed by the parser, until 21 the attributes are actually set by the parser. This way, we directly 22 create an inputType / shadow subtree of the right type. 23 24 I see a 1.4% speed up on speedometer (73.95 -> 75.0). 25 26 No new tests, no behavior change. 27 28 * dom/Element.cpp: 29 (WebCore::Element::parserSetAttributes): 30 (WebCore::Element::parserDidFinishParsingAttributes): 31 * dom/Element.h: 32 * html/HTMLInputElement.cpp: 33 (WebCore::HTMLInputElement::HTMLInputElement): 34 (WebCore::HTMLInputElement::create): 35 (WebCore::HTMLInputElement::updateType): 36 (WebCore::HTMLInputElement::runPostTypeUpdateTasks): 37 (WebCore::HTMLInputElement::ensureInputType): 38 (WebCore::HTMLInputElement::parseAttribute): 39 (WebCore::HTMLInputElement::parserDidFinishParsingAttributes): 40 * html/HTMLInputElement.h: 41 1 42 2014-11-10 Benjamin Poulain <bpoulain@apple.com> 2 43 -
trunk/Source/WebCore/dom/Element.cpp
r175212 r175852 1234 1234 ASSERT(!m_elementData); 1235 1235 1236 if (attributeVector.isEmpty()) 1237 return; 1238 1239 if (document().sharedObjectPool()) 1240 m_elementData = document().sharedObjectPool()->cachedShareableElementDataWithAttributes(attributeVector); 1241 else 1242 m_elementData = ShareableElementData::createWithAttributes(attributeVector); 1243 1244 // Use attributeVector instead of m_elementData because attributeChanged might modify m_elementData. 1245 for (unsigned i = 0; i < attributeVector.size(); ++i) 1246 attributeChanged(attributeVector[i].name(), nullAtom, attributeVector[i].value(), ModifiedDirectly); 1236 if (!attributeVector.isEmpty()) { 1237 if (document().sharedObjectPool()) 1238 m_elementData = document().sharedObjectPool()->cachedShareableElementDataWithAttributes(attributeVector); 1239 else 1240 m_elementData = ShareableElementData::createWithAttributes(attributeVector); 1241 1242 // Use attributeVector instead of m_elementData because attributeChanged might modify m_elementData. 1243 for (const auto& attribute : attributeVector) 1244 attributeChanged(attribute.name(), nullAtom, attribute.value(), ModifiedDirectly); 1245 } 1246 1247 parserDidFinishParsingAttributes(); 1248 } 1249 1250 void Element::parserDidFinishParsingAttributes() 1251 { 1247 1252 } 1248 1253 -
trunk/Source/WebCore/dom/Element.h
r175212 r175852 556 556 virtual void childrenChanged(const ChildChange&) override; 557 557 virtual void removeAllEventListeners() override final; 558 virtual void parserDidFinishParsingAttributes(); 558 559 559 560 void clearTabIndexExplicitlyIfNeeded(); -
trunk/Source/WebCore/html/HTMLInputElement.cpp
r175787 r175852 122 122 , m_hasTouchEventHandler(false) 123 123 #endif 124 , m_inputType(InputType::createText(*this)) 124 // m_inputType is lazily created when constructed by the parser to avoid constructing unnecessarily a text inputType and 125 // its shadow subtree, just to destroy them when the |type| attribute gets set by the parser to something else than 'text'. 126 , m_inputType(createdByParser ? nullptr : InputType::createText(*this)) 125 127 { 126 128 ASSERT(hasTagName(inputTag) || hasTagName(isindexTag)); … … 130 132 PassRefPtr<HTMLInputElement> HTMLInputElement::create(const QualifiedName& tagName, Document& document, HTMLFormElement* form, bool createdByParser) 131 133 { 134 bool shouldCreateShadowRootLazily = createdByParser; 132 135 RefPtr<HTMLInputElement> inputElement = adoptRef(new HTMLInputElement(tagName, document, form, createdByParser)); 133 inputElement->ensureUserAgentShadowRoot(); 136 if (!shouldCreateShadowRootLazily) 137 inputElement->ensureUserAgentShadowRoot(); 134 138 return inputElement.release(); 135 139 } … … 433 437 void HTMLInputElement::updateType() 434 438 { 439 ASSERT(m_inputType); 435 440 auto newType = InputType::create(*this, fastGetAttribute(typeAttr)); 436 441 bool hadType = m_hasType; … … 457 462 m_inputType->createShadowSubtree(); 458 463 updateInnerTextElementEditability(); 459 460 #if ENABLE(TOUCH_EVENTS)461 bool hasTouchEventHandler = m_inputType->hasTouchEventHandler();462 if (hasTouchEventHandler != m_hasTouchEventHandler) {463 if (hasTouchEventHandler)464 document().didAddTouchEventHandler(this);465 else466 document().didRemoveTouchEventHandler(this);467 m_hasTouchEventHandler = hasTouchEventHandler;468 }469 #endif470 464 471 465 setNeedsWillValidateCheck(); … … 503 497 attributeChanged(alignAttr, nullAtom, align->value()); 504 498 } 499 500 runPostTypeUpdateTasks(); 501 } 502 503 inline void HTMLInputElement::runPostTypeUpdateTasks() 504 { 505 ASSERT(m_inputType); 506 #if ENABLE(TOUCH_EVENTS) 507 bool hasTouchEventHandler = m_inputType->hasTouchEventHandler(); 508 if (hasTouchEventHandler != m_hasTouchEventHandler) { 509 if (hasTouchEventHandler) 510 document().didAddTouchEventHandler(this); 511 else 512 document().didRemoveTouchEventHandler(this); 513 m_hasTouchEventHandler = hasTouchEventHandler; 514 } 515 #endif 505 516 506 517 if (renderer()) … … 597 608 } 598 609 610 inline void HTMLInputElement::ensureInputType() 611 { 612 ASSERT(m_parsingInProgress); 613 if (m_inputType) 614 return; 615 616 if (!hasAttribute(typeAttr)) { 617 m_inputType = InputType::createText(*this); 618 ensureUserAgentShadowRoot(); 619 return; 620 } 621 622 m_hasType = true; 623 m_inputType = InputType::create(*this, fastGetAttribute(typeAttr)); 624 ensureUserAgentShadowRoot(); 625 registerForSuspensionCallbackIfNeeded(); 626 runPostTypeUpdateTasks(); 627 } 628 599 629 void HTMLInputElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 600 630 { 631 if (m_parsingInProgress) { 632 // A lot of the code below requires m_inputType to be initialized so make sure we do. 633 // By the time parseAttribute() is called during parsing anyway, all attributes have 634 // been set on the element already so there is no point in delaying m_inputType 635 // initialization further. 636 ensureInputType(); 637 } 638 601 639 if (name == nameAttr) { 602 640 removeFromRadioButtonGroup(); … … 706 744 } 707 745 746 void HTMLInputElement::parserDidFinishParsingAttributes() 747 { 748 ASSERT(m_inputType || !hasAttributes()); 749 ensureInputType(); 750 } 751 708 752 void HTMLInputElement::finishParsingChildren() 709 753 { -
trunk/Source/WebCore/html/HTMLInputElement.h
r175778 r175852 360 360 virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStyleProperties&) override; 361 361 virtual void finishParsingChildren() override; 362 virtual void parserDidFinishParsingAttributes() override final; 362 363 363 364 virtual void copyNonAttributePropertiesFromElement(const Element&) override; … … 399 400 virtual void requiredAttributeChanged() override; 400 401 402 void ensureInputType(); 401 403 void updateType(); 404 void runPostTypeUpdateTasks(); 402 405 403 406 virtual void subtreeHasChanged() override;
Note:
See TracChangeset
for help on using the changeset viewer.