Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(227)

Side by Side Diff: Source/core/dom/Element.cpp

Issue 18276003: Avoid N^2 walk placing renderers when building the render tree (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Adding test expectations Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Peter Kelly (pmk@post.com) 4 * (C) 2001 Peter Kelly (pmk@post.com)
5 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * (C) 2001 Dirk Mueller (mueller@kde.org)
6 * (C) 2007 David Smith (catfish.man@gmail.com) 6 * (C) 2007 David Smith (catfish.man@gmail.com)
7 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved. 7 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
8 * (C) 2007 Eric Seidel (eric@webkit.org) 8 * (C) 2007 Eric Seidel (eric@webkit.org)
9 * 9 *
10 * This library is free software; you can redistribute it and/or 10 * This library is free software; you can redistribute it and/or
(...skipping 1412 matching lines...) Expand 10 before | Expand all | Expand 10 after
1423 // is needed, but for now just assume a layout will be required. The diff code 1423 // is needed, but for now just assume a layout will be required. The diff code
1424 // in RenderObject::setStyle would need to be factored out so th at it could be reused. 1424 // in RenderObject::setStyle would need to be factored out so th at it could be reused.
1425 renderer()->setNeedsLayoutAndPrefWidthsRecalc(); 1425 renderer()->setNeedsLayoutAndPrefWidthsRecalc();
1426 } 1426 }
1427 return true; 1427 return true;
1428 } 1428 }
1429 } 1429 }
1430 return false; 1430 return false;
1431 } 1431 }
1432 1432
1433 PassRefPtr<RenderStyle> Element::styleForRenderer() 1433 PassRefPtr<RenderStyle> Element::styleForRenderer(int childIndex)
1434 { 1434 {
1435 if (hasCustomStyleCallbacks()) { 1435 if (hasCustomStyleCallbacks()) {
1436 if (RefPtr<RenderStyle> style = customStyleForRenderer()) 1436 if (RefPtr<RenderStyle> style = customStyleForRenderer())
1437 return style.release(); 1437 return style.release();
1438 } 1438 }
1439 1439
1440 return originalStyleForRenderer(); 1440 return originalStyleForRenderer(childIndex);
1441 } 1441 }
1442 1442
1443 PassRefPtr<RenderStyle> Element::originalStyleForRenderer() 1443 PassRefPtr<RenderStyle> Element::originalStyleForRenderer(int childIndex)
1444 { 1444 {
1445 return document()->styleResolver()->styleForElement(this); 1445 return document()->styleResolver()->styleForElement(this, childIndex);
1446 } 1446 }
1447 1447
1448 void Element::recalcStyle(StyleChange change) 1448 void Element::recalcStyle(StyleChange change, int childIndex)
1449 { 1449 {
1450 ASSERT(document()->inStyleRecalc()); 1450 ASSERT(document()->inStyleRecalc());
1451 1451
1452 if (hasCustomStyleCallbacks()) 1452 if (hasCustomStyleCallbacks())
1453 willRecalcStyle(change); 1453 willRecalcStyle(change);
1454 1454
1455 // Ref currentStyle in case it would otherwise be deleted when setting the n ew style in the renderer. 1455 // Ref currentStyle in case it would otherwise be deleted when setting the n ew style in the renderer.
1456 RefPtr<RenderStyle> currentStyle(renderStyle()); 1456 RefPtr<RenderStyle> currentStyle(renderStyle());
1457 bool hasParentStyle = parentNodeForRenderingAndStyle() ? static_cast<bool>(p arentNodeForRenderingAndStyle()->renderStyle()) : false; 1457 bool hasParentStyle = parentNodeForRenderingAndStyle() ? static_cast<bool>(p arentNodeForRenderingAndStyle()->renderStyle()) : false;
1458 bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules(); 1458 bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules();
1459 bool hasIndirectAdjacentRules = childrenAffectedByForwardPositionalRules(); 1459 bool hasIndirectAdjacentRules = childrenAffectedByForwardPositionalRules();
1460 1460
1461 if ((change > NoChange || needsStyleRecalc())) { 1461 if ((change > NoChange || needsStyleRecalc())) {
1462 if (hasRareData()) 1462 if (hasRareData())
1463 elementRareData()->resetComputedStyle(); 1463 elementRareData()->resetComputedStyle();
1464 } 1464 }
1465 if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) { 1465 if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) {
1466 StyleChange localChange = Detach; 1466 StyleChange localChange = Detach;
1467 RefPtr<RenderStyle> newStyle; 1467 RefPtr<RenderStyle> newStyle;
1468 if (currentStyle) { 1468 if (currentStyle) {
1469 // FIXME: This still recalcs style twice when changing display types , but saves 1469 // FIXME: This still recalcs style twice when changing display types , but saves
1470 // us from recalcing twice when going from none -> anything else whi ch is more 1470 // us from recalcing twice when going from none -> anything else whi ch is more
1471 // common, especially during lazy attach. 1471 // common, especially during lazy attach.
1472 newStyle = styleForRenderer(); 1472 newStyle = styleForRenderer(childIndex);
1473 localChange = Node::diff(currentStyle.get(), newStyle.get(), documen t()); 1473 localChange = Node::diff(currentStyle.get(), newStyle.get(), documen t());
1474 } else if (attached() && isActiveInsertionPoint(this)) { 1474 } else if (attached() && isActiveInsertionPoint(this)) {
1475 // Active InsertionPoints will never have renderers so there's no re ason to 1475 // Active InsertionPoints will never have renderers so there's no re ason to
1476 // reattach them repeatedly once they're already attached. 1476 // reattach them repeatedly once they're already attached.
1477 localChange = change; 1477 localChange = change;
1478 } 1478 }
1479 if (localChange == Detach) { 1479 if (localChange == Detach) {
1480 AttachContext reattachContext; 1480 AttachContext reattachContext;
1481 reattachContext.resolvedStyle = newStyle.get(); 1481 reattachContext.resolvedStyle = newStyle.get();
1482 reattach(reattachContext); 1482 reattach(reattachContext);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1526 } 1526 }
1527 1527
1528 if (shouldRecalcStyle(change, this)) 1528 if (shouldRecalcStyle(change, this))
1529 updatePseudoElement(BEFORE, change); 1529 updatePseudoElement(BEFORE, change);
1530 1530
1531 // FIXME: This check is good enough for :hover + foo, but it is not good eno ugh for :hover + foo + bar. 1531 // FIXME: This check is good enough for :hover + foo, but it is not good eno ugh for :hover + foo + bar.
1532 // For now we will just worry about the common case, since it's a lot tricki er to get the second case right 1532 // For now we will just worry about the common case, since it's a lot tricki er to get the second case right
1533 // without doing way too much re-resolution. 1533 // without doing way too much re-resolution.
1534 bool forceCheckOfNextElementSibling = false; 1534 bool forceCheckOfNextElementSibling = false;
1535 bool forceCheckOfAnyElementSibling = false; 1535 bool forceCheckOfAnyElementSibling = false;
1536 for (Node *n = firstChild(); n; n = n->nextSibling()) { 1536 int indexForChild = 0;
esprehn 2013/07/11 01:24:32 childIndex
leviw_travelin_and_unemployed 2013/07/11 01:35:11 childIndex is an input parameter.
1537 if (hasDirectAdjacentRules || hasIndirectAdjacentRules) {
1538 for (Node *n = firstChild(); n; n = n->nextSibling()) {
1539 ++indexForChild;
1540 if (!n->isElementNode())
1541 continue;
1542 Element* element = toElement(n);
1543 bool childRulesChanged = element->needsStyleRecalc() && element->sty leChangeType() == FullStyleChange;
1544 if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling ))
esprehn 2013/07/11 01:24:32 Remove extra parens?
leviw_travelin_and_unemployed 2013/07/11 01:35:11 Good call.
1545 element->setNeedsStyleRecalc();
1546 forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjac entRules;
1547 forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (ch ildRulesChanged && hasIndirectAdjacentRules);
1548 }
1549 }
1550 // FIXME: Reversing the loop we call recalcStyle avoids an N^2 walk through the DOM to find the next renderer
1551 // to insert before. The logic in NodeRenderingContext should be improved to make this unnecessary.
1552 for (Node *n = lastChild(); n; n = n->previousSibling()) {
esprehn 2013/07/11 01:24:32 Can we rename n to child? I did this in my patch.
1553 --indexForChild;
1537 if (n->isTextNode()) { 1554 if (n->isTextNode()) {
1538 toText(n)->recalcTextStyle(change); 1555 toText(n)->recalcTextStyle(change);
1539 continue; 1556 continue;
1540 } 1557 }
1541 if (!n->isElementNode()) 1558 if (!n->isElementNode())
1542 continue; 1559 continue;
1543 Element* element = toElement(n); 1560 Element* element = toElement(n);
1544 bool childRulesChanged = element->needsStyleRecalc() && element->styleCh angeType() == FullStyleChange;
1545 if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling))
1546 element->setNeedsStyleRecalc();
1547 if (shouldRecalcStyle(change, element)) { 1561 if (shouldRecalcStyle(change, element)) {
1548 parentPusher.push(); 1562 parentPusher.push();
1549 element->recalcStyle(change); 1563 element->recalcStyle(change, max(indexForChild + 1, 0));
esprehn 2013/07/11 01:24:32 Above just do childIndex = max(childIndex - 1, 0)
leviw_travelin_and_unemployed 2013/07/11 01:35:11 We need to decrement throughout the entire loop, n
1550 } 1564 }
1551 forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentR ules;
1552 forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childR ulesChanged && hasIndirectAdjacentRules);
1553 } 1565 }
1554 1566
1555 if (shouldRecalcStyle(change, this)) 1567 if (shouldRecalcStyle(change, this))
1556 updatePseudoElement(AFTER, change); 1568 updatePseudoElement(AFTER, change);
1557 1569
1558 clearNeedsStyleRecalc(); 1570 clearNeedsStyleRecalc();
1559 clearChildNeedsStyleRecalc(); 1571 clearChildNeedsStyleRecalc();
1560 1572
1561 if (hasCustomStyleCallbacks()) 1573 if (hasCustomStyleCallbacks())
1562 didRecalcStyle(change); 1574 didRecalcStyle(change);
(...skipping 2033 matching lines...) Expand 10 before | Expand all | Expand 10 after
3596 return 0; 3608 return 0;
3597 } 3609 }
3598 3610
3599 Attribute* UniqueElementData::attributeItem(unsigned index) 3611 Attribute* UniqueElementData::attributeItem(unsigned index)
3600 { 3612 {
3601 ASSERT_WITH_SECURITY_IMPLICATION(index < length()); 3613 ASSERT_WITH_SECURITY_IMPLICATION(index < length());
3602 return &m_attributeVector.at(index); 3614 return &m_attributeVector.at(index);
3603 } 3615 }
3604 3616
3605 } // namespace WebCore 3617 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698