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

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

Issue 15871005: Avoid N^2 walk placing renderers when building the render tree (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Reversing the snapshotting logic to fix a bug, and updating test expectations. Created 7 years, 6 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
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 1329 matching lines...) Expand 10 before | Expand all | Expand 10 after
1340 // is needed, but for now just assume a layout will be required. The diff code 1340 // is needed, but for now just assume a layout will be required. The diff code
1341 // in RenderObject::setStyle would need to be factored out so th at it could be reused. 1341 // in RenderObject::setStyle would need to be factored out so th at it could be reused.
1342 renderer()->setNeedsLayoutAndPrefWidthsRecalc(); 1342 renderer()->setNeedsLayoutAndPrefWidthsRecalc();
1343 } 1343 }
1344 return true; 1344 return true;
1345 } 1345 }
1346 } 1346 }
1347 return false; 1347 return false;
1348 } 1348 }
1349 1349
1350 PassRefPtr<RenderStyle> Element::styleForRenderer() 1350 PassRefPtr<RenderStyle> Element::styleForRenderer(int childIndex)
1351 { 1351 {
1352 if (hasCustomStyleCallbacks()) { 1352 if (hasCustomStyleCallbacks()) {
1353 if (RefPtr<RenderStyle> style = customStyleForRenderer()) 1353 if (RefPtr<RenderStyle> style = customStyleForRenderer())
1354 return style.release(); 1354 return style.release();
1355 } 1355 }
1356 1356
1357 return originalStyleForRenderer(); 1357 return originalStyleForRenderer(childIndex);
1358 } 1358 }
1359 1359
1360 PassRefPtr<RenderStyle> Element::originalStyleForRenderer() 1360 PassRefPtr<RenderStyle> Element::originalStyleForRenderer(int childIndex)
1361 { 1361 {
1362 return document()->styleResolver()->styleForElement(this); 1362 return document()->styleResolver()->styleForElement(this, childIndex);
1363 } 1363 }
1364 1364
1365 void Element::recalcStyle(StyleChange change) 1365 void Element::recalcStyle(StyleChange change, int childIndex)
1366 { 1366 {
1367 ASSERT(document()->inStyleRecalc()); 1367 ASSERT(document()->inStyleRecalc());
1368 1368
1369 if (hasCustomStyleCallbacks()) 1369 if (hasCustomStyleCallbacks())
1370 willRecalcStyle(change); 1370 willRecalcStyle(change);
1371 1371
1372 // Ref currentStyle in case it would otherwise be deleted when setting the n ew style in the renderer. 1372 // Ref currentStyle in case it would otherwise be deleted when setting the n ew style in the renderer.
1373 RefPtr<RenderStyle> currentStyle(renderStyle()); 1373 RefPtr<RenderStyle> currentStyle(renderStyle());
1374 bool hasParentStyle = parentNodeForRenderingAndStyle() ? static_cast<bool>(p arentNodeForRenderingAndStyle()->renderStyle()) : false; 1374 bool hasParentStyle = parentNodeForRenderingAndStyle() ? static_cast<bool>(p arentNodeForRenderingAndStyle()->renderStyle()) : false;
1375 bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules(); 1375 bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules();
1376 bool hasIndirectAdjacentRules = childrenAffectedByForwardPositionalRules(); 1376 bool hasIndirectAdjacentRules = childrenAffectedByForwardPositionalRules();
1377 1377
1378 if ((change > NoChange || needsStyleRecalc())) { 1378 if ((change > NoChange || needsStyleRecalc())) {
1379 if (hasRareData()) 1379 if (hasRareData())
1380 elementRareData()->resetComputedStyle(); 1380 elementRareData()->resetComputedStyle();
1381 } 1381 }
1382 if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) { 1382 if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) {
1383 StyleChange localChange = Detach; 1383 StyleChange localChange = Detach;
1384 RefPtr<RenderStyle> newStyle; 1384 RefPtr<RenderStyle> newStyle;
1385 if (currentStyle) { 1385 if (currentStyle) {
1386 // FIXME: This still recalcs style twice when changing display types , but saves 1386 // FIXME: This still recalcs style twice when changing display types , but saves
1387 // us from recalcing twice when going from none -> anything else whi ch is more 1387 // us from recalcing twice when going from none -> anything else whi ch is more
1388 // common, especially during lazy attach. 1388 // common, especially during lazy attach.
1389 newStyle = styleForRenderer(); 1389 newStyle = styleForRenderer(childIndex);
1390 localChange = Node::diff(currentStyle.get(), newStyle.get(), documen t()); 1390 localChange = Node::diff(currentStyle.get(), newStyle.get(), documen t());
1391 } 1391 }
1392 if (localChange == Detach) { 1392 if (localChange == Detach) {
1393 // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along. 1393 // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along.
1394 reattach(); 1394 reattach();
1395 // attach recalculates the style for all children. No need to do it twice. 1395 // attach recalculates the style for all children. No need to do it twice.
1396 clearNeedsStyleRecalc(); 1396 clearNeedsStyleRecalc();
1397 clearChildNeedsStyleRecalc(); 1397 clearChildNeedsStyleRecalc();
1398 1398
1399 if (hasCustomStyleCallbacks()) 1399 if (hasCustomStyleCallbacks())
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1435 } 1435 }
1436 1436
1437 if (shouldRecalcStyle(change, this)) 1437 if (shouldRecalcStyle(change, this))
1438 updatePseudoElement(BEFORE, change); 1438 updatePseudoElement(BEFORE, change);
1439 1439
1440 // FIXME: This check is good enough for :hover + foo, but it is not good eno ugh for :hover + foo + bar. 1440 // FIXME: This check is good enough for :hover + foo, but it is not good eno ugh for :hover + foo + bar.
1441 // For now we will just worry about the common case, since it's a lot tricki er to get the second case right 1441 // For now we will just worry about the common case, since it's a lot tricki er to get the second case right
1442 // without doing way too much re-resolution. 1442 // without doing way too much re-resolution.
1443 bool forceCheckOfNextElementSibling = false; 1443 bool forceCheckOfNextElementSibling = false;
1444 bool forceCheckOfAnyElementSibling = false; 1444 bool forceCheckOfAnyElementSibling = false;
1445 int indexForChild = 0;
1445 for (Node *n = firstChild(); n; n = n->nextSibling()) { 1446 for (Node *n = firstChild(); n; n = n->nextSibling()) {
1447 ++indexForChild;
1446 if (n->isTextNode()) { 1448 if (n->isTextNode()) {
1447 toText(n)->recalcTextStyle(change); 1449 toText(n)->recalcTextStyle(change);
1448 continue; 1450 continue;
1449 } 1451 }
1450 if (!n->isElementNode()) 1452 if (!n->isElementNode())
1451 continue; 1453 continue;
1452 Element* element = toElement(n); 1454 Element* element = toElement(n);
1453 bool childRulesChanged = element->needsStyleRecalc() && element->styleCh angeType() == FullStyleChange; 1455 bool childRulesChanged = element->needsStyleRecalc() && element->styleCh angeType() == FullStyleChange;
1454 if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling)) 1456 if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling))
1455 element->setNeedsStyleRecalc(); 1457 element->setNeedsStyleRecalc();
1456 if (shouldRecalcStyle(change, element)) {
1457 parentPusher.push();
1458 element->recalcStyle(change);
1459 }
1460 forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentR ules; 1458 forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentR ules;
1461 forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childR ulesChanged && hasIndirectAdjacentRules); 1459 forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childR ulesChanged && hasIndirectAdjacentRules);
1462 } 1460 }
1461 // FIXME: Reversing the loop we call recalcStyle avoids an N^2 walk through the DOM to find the next renderer
1462 // to insert before. The logic in NodeRenderingContext should be improved to make this unnecessary.
1463 for (Node *n = lastChild(); n; n = n->previousSibling()) {
1464 if (n->isTextNode() || !n->isElementNode())
esprehn 2013/06/05 00:12:26 You don't need to check for isTextNode, it's alrea
1465 continue;
1466 Element* element = toElement(n);
1467 if (shouldRecalcStyle(change, element)) {
1468 parentPusher.push();
1469 element->recalcStyle(change, indexForChild);
1470 }
1471 --indexForChild;
1472 }
1463 1473
1464 if (shouldRecalcStyle(change, this)) 1474 if (shouldRecalcStyle(change, this))
1465 updatePseudoElement(AFTER, change); 1475 updatePseudoElement(AFTER, change);
1466 1476
1467 clearNeedsStyleRecalc(); 1477 clearNeedsStyleRecalc();
1468 clearChildNeedsStyleRecalc(); 1478 clearChildNeedsStyleRecalc();
1469 1479
1470 if (hasCustomStyleCallbacks()) 1480 if (hasCustomStyleCallbacks())
1471 didRecalcStyle(change); 1481 didRecalcStyle(change);
1472 InspectorInstrumentation::didRecalculateStyleForElement(this); 1482 InspectorInstrumentation::didRecalculateStyleForElement(this);
(...skipping 1630 matching lines...) Expand 10 before | Expand all | Expand 10 after
3103 return 0; 3113 return 0;
3104 } 3114 }
3105 3115
3106 Attribute* UniqueElementData::attributeItem(unsigned index) 3116 Attribute* UniqueElementData::attributeItem(unsigned index)
3107 { 3117 {
3108 ASSERT_WITH_SECURITY_IMPLICATION(index < length()); 3118 ASSERT_WITH_SECURITY_IMPLICATION(index < length());
3109 return &m_attributeVector.at(index); 3119 return &m_attributeVector.at(index);
3110 } 3120 }
3111 3121
3112 } // namespace WebCore 3122 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698